Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Command-line option for displaying targets #5032

Merged
merged 33 commits into from
Feb 18, 2020

Conversation

szaliszali
Copy link
Contributor

This feature request was lying around for a few years, I'm submitting a simple implementation for review and further discussion. As @AndyGerlicher kindly pointed out the already existing preprocess option, it seemed logical to take the same approach for this one.

Sample output for a C# project:

Microsoft (R) Build Engine version 16.5.0-dev-20056-01+fb441875f for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

CreateManifestResourceNames
ResolveCodeAnalysisRuleSet
XamlPreCompile
ShimReferencePathsWhenCommonTargetsDoesNotUnderstandReferenceAssemblies
_BeforeVBCSCoreCompile
[.... 200+ lines omitted ....]
XsdResolveReferencePath
CleanXsdCodeGen
_SetTargetFrameworkMonikerAttribute
EnsureNuGetPackageBuildImports

Fixes #33

@dnfclas
Copy link

dnfclas commented Jan 6, 2020

CLA assistant check
All CLA requirements met.

Copy link
Member

@Forgind Forgind left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! These changes look good to me with just a few minor issues.

@@ -1056,6 +1060,7 @@ string outputResultsCache
ToolsetDefinitionLocations toolsetDefinitionLocations = ToolsetDefinitionLocations.Default;

bool preprocessOnly = preprocessWriter != null && !FileUtilities.IsSolutionFilename(projectFile);
bool targetsOnly = targetsWriter != null && !FileUtilities.IsSolutionFilename(projectFile);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change loadProjectReadOnly (10 lines down) to be !preprocessOnly && !targetsOnly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not seem logical for me at first glance, because printing the targets should be a read-only operation.

Also, it looks like the setting will be ignored anyway (see this comment).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I was suggesting it should be read-only, but I might have gotten it flipped. @rainersigwald, do you know better? Otherwise, this looks good to me.

src/MSBuild.UnitTests/CommandLineSwitches_Tests.cs Outdated Show resolved Hide resolved
src/MSBuild.UnitTests/CommandLineSwitches_Tests.cs Outdated Show resolved Hide resolved
src/MSBuild/Resources/Strings.resx Outdated Show resolved Hide resolved
@cdmihai
Copy link
Contributor

cdmihai commented Jan 14, 2020

_BeforeVBCSCoreCompile
[.... 200+ lines omitted ....]
XsdResolveReferencePath

I doubt this would actually be practically useful to anyone. Since MSBuild does not have any information hiding capabilities (you get ALL the hundreds of meaningless targets, not just the entry graph wide operations supported by the current mix of "SDKs"), and since MSBuild does not differentiate the graph wide entry targets (Build, Clean, Rebuild, Test, Restore, Pack) in any way from the implementation targets, this feature will just lead to information overload. It would interesting though, if we introduced graph wide entry targets as first class entities in the language.

I'd be quite curious to learn of a practical usage to this.

@Forgind
Copy link
Member

Forgind commented Jan 14, 2020

One possible use I thought of was if you know roughly what you need but don't know exactly what the target is called. This would make it easier to find the exact target. You can also try to add custom targets, and if they don't show up, you know you didn't add them properly.

The original issue has 30 upvotes and has gotten some activity within the past 6 months, so although it's an old issue, I think it's worth taking this pr.

@AndyGerlicher
Copy link
Contributor

One thing I worry about on this feature is it might give the implication of a target contract. Looking at the other commands provided as examples, grunt --help or rake --tasks to me seem to imply those are operational things that will occur or are available to be used. In MSBuild, many of the targets are internal implementations and should really be considered "private" and not exposed like this. The language really isn't setup as a discoverable catalog of functions. Maybe one mitigation would be to filter out all targets starting with _? It's largely convention based, but it would help some with that.

The other is this is pretty trivial to get as a one-off. It seems surprising to me that this would be common enough to go into MSBuild proper. Again unless it's more of a let's see what's available to hook into which is my original concern.

@@ -1417,6 +1417,11 @@ public void SaveLogicalProject(TextWriter writer)
implementation.SaveLogicalProject(writer);
}

public void PrintTargets(TextWriter writer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather have the Project API only return targets, and not deal with the extra problem domain of printing object model things to streams.

@szaliszali
Copy link
Contributor Author

I'm happy to see that the PR sparked a bit of conversation [also, a bit less happy about the merge conflict]. I'll update as soon as I have a bit of free time.

About usability of the output: I also think that dumping 200 targets is not the most useful thing we could do. For now, I can consider this feature more like a debugging tool than quick help for the confused end-user. Also, would not recommend skipping targets based on naming convention.

@szaliszali
Copy link
Contributor Author

Short explanation for the additional error handler: during testing I experienced several error modes:

  • missing project file: prints error and halts before doing any work
    image
  • fatal error during project file loading (e.g. a random text file as project): finds project file and starts loading, then prints error (in red) and exits
    image
  • valid project with something broken during processing build files (e.g. SDK resolver is missing from msbuild directory): in this case, I could not figure out why the error message is printed in one case and not in the other
    • error message (in red) was printed
      image
    • no error message was printed and this could confuse users what is (not) happening, this is why I decided to add the extra error handler
      image

I chose this simple way of displaying the message instead of real loggers because I found the logger setup and logging too complicated for this simple task

Copy link
Member

@rainersigwald rainersigwald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

The team talked about the possibility of sorting the results, but decided not to bother:

  • The ideal sort order is by dependency order, but that's not statically knowable.
  • If you just want alphabetical sort, it's easy to pipe to sort or similar.

}
catch (Exception ex)
{
var message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("TargetsCouldNotBePrinted", ex.Message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("TargetsCouldNotBePrinted", ex.Message);
var message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("TargetsCouldNotBePrinted", ex);

This preserves the call stack which can make fixing bugs that report this error MUCH easier.

{
Project project = projectCollection.LoadProject(projectFile, globalProperties, toolsVersion);

targetsWriter.WriteLine(string.Join(Environment.NewLine, project.Targets.Keys));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you call this in a loop?

Suggested change
targetsWriter.WriteLine(string.Join(Environment.NewLine, project.Targets.Keys));
foreach (string target in project.Targets.Keys)
{
targetsWriter.WriteLine(target);
}

That way we don't have to allocate a big string? (it's not super critical here, but it's good practice)

…line

# Conflicts:
#	src/MSBuild/Resources/Strings.resx
#	src/MSBuild/Resources/xlf/Strings.cs.xlf
#	src/MSBuild/Resources/xlf/Strings.de.xlf
#	src/MSBuild/Resources/xlf/Strings.en.xlf
#	src/MSBuild/Resources/xlf/Strings.es.xlf
#	src/MSBuild/Resources/xlf/Strings.fr.xlf
#	src/MSBuild/Resources/xlf/Strings.it.xlf
#	src/MSBuild/Resources/xlf/Strings.ja.xlf
#	src/MSBuild/Resources/xlf/Strings.ko.xlf
#	src/MSBuild/Resources/xlf/Strings.pl.xlf
#	src/MSBuild/Resources/xlf/Strings.pt-BR.xlf
#	src/MSBuild/Resources/xlf/Strings.ru.xlf
#	src/MSBuild/Resources/xlf/Strings.tr.xlf
#	src/MSBuild/Resources/xlf/Strings.zh-Hans.xlf
#	src/MSBuild/Resources/xlf/Strings.zh-Hant.xlf
Copy link
Member

@Forgind Forgind left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
Thanks!

@rainersigwald rainersigwald merged commit d7af217 into dotnet:master Feb 18, 2020
@rainersigwald
Copy link
Member

Thanks @szaliszali! This should go out with Visual Studio 16.6 preview 1 (at some point in the future).

@videoguy
Copy link

Is it available in VS 2019?
I tried, it doesn't seem to be supported.

@Forgind
Copy link
Member

Forgind commented Jan 11, 2023

It should be. What exact version of VS 2019 are you using? 16.11?

@videoguy
Copy link

videoguy commented Jan 11, 2023

VS 2019 16.9.25 build.
Just started an update of VS. Let me check once the update completes.

@videoguy
Copy link

After the update, it is working. I am wondering if there is something for solution file (.sln) as well.

@rainersigwald
Copy link
Member

@videoguy not today; that's tracked by #7697.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Command-line option for displaying targets
8 participants