-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Improve MSBuild argument parsing and tracking, and use that to set RestoreProperties that optimize Restore for large projects #49526
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
Conversation
a3c3554
to
1f8c0ac
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a new mechanism for handling restore properties by introducing a structured MSBuild arguments object (MSBuildArgs) and converting all MSBuild property–forwarding from the legacy dash-prefix (‑property:) style to the new double‐dash (“--property:”) convention. Key changes include refactoring command-line parsing and forwarding logic across multiple commands, updating tests to match the new syntax, and adding support for restore‐only properties that disable default item globbing.
Reviewed Changes
Copilot reviewed 46 out of 47 changed files in this pull request and generated 2 comments.
File | Description |
---|---|
test/dotnet.Tests/CommandTests/* | Updated tests to assert ApplicationArgs and revised MSBuild property syntax |
src/Cli/dotnet/* and src/Cli/Microsoft.DotNet.Cli.Utils/* | Refactored MSBuild forwarding and option parsing to use the new MSBuildArgs structure and “--property:” style |
src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs | Introduced a structured model for accumulating MSBuild arguments with proper merging of global and restore properties |
Comments suppressed due to low confidence (1)
src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildArgs.cs:115
- It would be beneficial to add a comment clarifying that duplicate keys from additional restore properties will overwrite existing ones, to aid future maintainability and user understanding.
public void ApplyPropertiesToRestore()
src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildForwardingAppWithoutLogging.cs
Show resolved
Hide resolved
There's only one interesting failing test - Microsoft.DotNet.Tests.PackagedCommandTests.CanInvokeToolWhosePackageNameIsDifferentFromDllName. This test is intended to show that we can invoke tools that are pulled in via the mostly-deprecated I'm inclined to remove this test. |
7372306
to
f12508f
Compare
b03968d
to
02712c5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this PR is so large, I've ignored most of my super minor nits I'd normally point out (extra/missing spaces, extra newlines, comments starting with lowercase letters, odd formatting, use of !
, etc.). The core changes seem solid.
src/Cli/dotnet/CommandFactory/CommandResolution/ProjectToolsCommandResolver.cs
Outdated
Show resolved
Hide resolved
System.CommandLine.Command command, | ||
Argument<string[]> catchAllUserInputArgument, | ||
Func<MSBuildArgs, string, VirtualProjectBuildingCommand> configureVirtualCommand, | ||
Func<MSBuildArgs, string?, CommandBase> createPhysicalCommand, | ||
IEnumerable<Option> optionsToUseWhenParsingMSBuildFlags, | ||
ParseResult parseResult, | ||
string? msbuildPath = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little funky. Maybe a class/record to hold this stuff just as a DTO to send to this command?
@@ -95,4 +95,15 @@ | |||
<Using Include="System.Collections.Generic.Dictionary%3CMicrosoft.NET.Sdk.WorkloadManifestReader.WorkloadId, Microsoft.NET.Sdk.WorkloadManifestReader.WorkloadDefinition%3E" Alias="WorkloadCollection" /> | |||
</ItemGroup> | |||
|
|||
<!-- NOTE: only works for fast-path code changes --> | |||
<Target Name="CopyToRedistFastPath" AfterTargets="AfterBuild"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is curious. Does this fix the issue where rebuilding the CLI I wasn't always getting new updates? I'd end up needing to do a full new build to get certain things to work that I've changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YES! But only for the subset of things that are actually contained in the dotnet.dll. This is totally a hack. If you change Targets, or something in the Cli.Utils.dll, etc - no benefit. Even so it's massively sped up my cycle times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, I've long wanted to add something like this. I've been running manually this command every time I built dotnet CLI :)
cp .\artifacts\bin\dotnet\Debug\net10.0\dotnet.dll .\artifacts\bin\redist\Debug\dotnet\sdk\10.0.100-dev\
test/dotnet.Tests/CommandTests/MSBuild/GivenDotnetOsArchOptions.cs
Outdated
Show resolved
Hide resolved
@@ -9,32 +9,6 @@ public GivenParserDirectives(ITestOutputHelper log) : base(log) | |||
{ | |||
} | |||
|
|||
[Fact] | |||
public void ItCanInvokeDiagramDirective() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these tests just no longer valid or...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diagram directive is a S.CL builtin - and it's not user-facing. It's not a relevant thing to test IMO.
@jjonescz do you have a sec to take a look at Microsoft.DotNet.Cli.Run.Tests.RunFileTests.NoRestore_01 and see if I messed something up on this branch? When I debug this test it seems to work, but when I run the test it fails. It feels like a timing issue? The output logs for the test are: Executing 'dotnet run --no-restore Program.cs':
》__________________________________________________
》Project "E:\Code\dotnet-sdk\artifacts\tmp\Debug\NoRestore_01\Program.csproj" (Build target(s)):
》
》E:\Code\dotnet-sdk\artifacts\bin\redist\Debug\dotnet\sdk\10.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(266,5): error NETSDK1004: Assets file 'C:\Users\chusk\AppData\Local\Temp\dotnet\runfile\Program-44d8093e140b3ceefcb5c0b5d4e6b101fc1ef03cc861347d6b511999f0a8ff6c\obj\project.assets.json' not found. Run a NuGet package restore to generate this file.
》Done building project "Program.csproj" -- FAILED.
❌
❌The build failed. Fix the build errors and run again.
Command 'dotnet run --no-restore Program.cs' exited with exit code 1.
Executing 'dotnet restore Program.cs':
》__________________________________________________
》Project "E:\Code\dotnet-sdk\artifacts\tmp\Debug\NoRestore_01\Program.csproj" (Restore target(s)):
》
》Restored E:\Code\dotnet-sdk\artifacts\tmp\Debug\NoRestore_01\Program.csproj (in 349 ms).
Command 'dotnet restore Program.cs' exited with exit code 0.
Executing 'dotnet run --no-restore Program.cs /bl:{}':
》Warning: Binary log option was specified but build will be skipped because output is up to date, specify '--no-cache' to force build.
❌Unhandled exception: An error occurred trying to start process 'C:\Users\chusk\AppData\Local\Temp\dotnet\runfile\Program-44d8093e140b3ceefcb5c0b5d4e6b101fc1ef03cc861347d6b511999f0a8ff6c\bin\debug\Program.exe' with working directory 'E:\Code\dotnet-sdk\artifacts\tmp\Debug\NoRestore_01'. The system cannot find the file specified.
Command 'dotnet run --no-restore Program.cs /bl:{}' exited with exit code 1. and what it seems like is that somehow a 'completed' build is tracked without the actual build occurring - which leads to the invocation of the supposedly-built binary failing. |
… for .NET Framework the same way we do for other projects that consume it.
It's important that per-command default behaviors come first in the list of args to parse so that user-provided values can override them.
…arget arg parsing
c257d1e
to
2a5ce81
Compare
Co-authored-by: Jan Jones <[email protected]>
The premise of this PR is that we would like to set some properties during Restore-time only that disable certain kinds of default globbing behaviors - those for Compile, EmbeddedResource, and None items. #49415 has the details of why we would want to do this.
MSBuild has a facility for passing properties that only apply during a Restore:
--restoreproperty
. The caveat to this is that as soon as a single--restoreproperty
is passed, the engine no longer uses any of the--property
values passed to that same invocation. This means that we need a way to:--restoreproperty
values--property
values--property
values into--restoreproperty
values as well, so that the Restore has a similar execution/evaluation environment as its associated build.To do this, we
--restoreproperty
structure.With this new structure in place, we can set the three restoreproperties that control the three item types in question, and we can do so in a way that respects any user-provided properties/restoreproperties that may override our defaults as well.
Every other change in this PR is a result of this approach. Over time, we can model more parts of the MSBuild CLI (targets, binlogs, logger arguments, etc) and expand the scope of the structured MSBuild arguments object, to provide more confidence/control.
I did model properties and targets in this new approach as well - so we have most of the common use cases accurately modeled and understood now.