Conversation
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
57310f0 to
696d06f
Compare
696d06f to
5082e63
Compare
5082e63 to
2f115e5
Compare
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Enables MSBuild-backed CLI commands when running the Native AOT dotnet entry point by registering SDK resolvers at AOT startup, wiring command parsers/actions into the AOT command tree, and extending the AOT test suite to validate forwarding/evaluation behavior.
Changes:
- Register MSBuild SDK resolvers during Native AOT startup and configure MSBuild-backed commands (
build,clean,msbuild,restore,pack,publish) for the AOT command tree. - Add AOT-safe evaluation path for directive-free virtual projects and expand AOT tests to cover command parsing/fallbacks and versioned-SDK forwarding (including PackRelease/PublishRelease evaluation).
- Update AOT design/docs and scope the temporary IL2104/IL3053 “not as error” policy to the Native AOT CLI project.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| test/dotnet-aot.Tests/NativeEntryPointTests.cs | Adjust fallback test to use an actually-unsupported command under the new AOT command set. |
| test/dotnet-aot.Tests/MSBuildEvaluationTests.cs | Add coverage for MSBuild forwarding, PackRelease/PublishRelease evaluation, project completions, and virtual-project evaluation. |
| test/dotnet-aot.Tests/AotParserTests.cs | Expand parser tests for newly-enabled commands and validate managed fallback for unsupported scenarios. |
| src/Microsoft.DotNet.ProjectTools/VirtualProjectBuilder.cs | Add directive-free project instance creation and refactor project-text creation to support AOT-safe evaluation. |
| src/Cli/dotnet/ReleasePropertyProjectLocator.cs | Make release-property evaluation usable in AOT-enabled paths and clean up AOT-related annotations/usings. |
| src/Cli/dotnet/Parser.cs | Configure additional MSBuild-backed commands in the AOT action configuration. |
| src/Cli/dotnet/NuGetSignatureVerificationEnabler.cs | Allow signature-verification environment wiring for MSBuild-forwarded apps in AOT builds. |
| src/Cli/dotnet/Extensions/ParseResultExtensions.cs | Route file-based app detection through VirtualProjectBuilder now that MSBuild is available in AOT. |
| src/Cli/dotnet/Commands/Run/VirtualProjectBuildingCommand.cs | Introduce AOT-safe evaluation-only behavior (no directives) and ensure execution remains managed-only via fallback. |
| src/Cli/dotnet/Commands/Publish/PublishCommandParser.cs | Remove AOT-blocking annotation to allow wiring in AOT command tree. |
| src/Cli/dotnet/Commands/Publish/PublishCommand.cs | Ensure FromArgs forwards msbuildPath and remove AOT-blocking annotation. |
| src/Cli/dotnet/Commands/Pack/PackCommandParser.cs | Remove AOT-blocking annotation to allow wiring in AOT command tree. |
| src/Cli/dotnet/Commands/Pack/PackCommand.cs | Guard .nuspec in-process NuGet packing under AOT and remove AOT-blocking annotation. |
| src/Cli/dotnet/Commands/DotNetCommandFactory.cs | Enable virtual/physical command creation logic for AOT by removing dynamic-code gating and broadening virtual factory return type. |
| src/Cli/dotnet/Commands/Clean/CleanCommandParser.cs | Keep clean file-based-apps managed-only under AOT via explicit fallback action. |
| src/Cli/dotnet-aot/SdkRootResolution.md | Update documentation to reflect new command coverage and telemetry expectations for managed vs AOT fallbacks. |
| src/Cli/dotnet-aot/NativeEntryPoint.cs | Register SDK resolvers during AOT startup to support MSBuild evaluations/forwarding. |
| src/Cli/dotnet-aot/dotnet-aot.csproj | Scope IL2104/IL3053 “not as error” policy to the AOT CLI project with rationale. |
| src/Cli/dotnet-aot/DESIGN.md | Update design doc to reflect MSBuild-backed command enablement and file-based app evaluation behavior. |
| src/Cli/dotnet-aot/AotSourceFiles.props | Include additional command sources needed for MSBuild-backed commands in the AOT build. |
2f115e5 to
89a8ded
Compare
0071895 to
3df5596
Compare
3df5596 to
fa38bc8
Compare
e7eacf0 to
59459b9
Compare
|
@jjonescz ok, I've revamped this a bit after the run-file changes that Jeremy was working on - care to take another look? |
Preserve the cached-run implementation's Native AOT guards while retaining directive-free project evaluation for MSBuild-backed commands. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Restore existing member and helper structure where possible, keep the managed-only analyzer suppression scoped to the MSBuild block, and consolidate repetitive parser tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Keep validating that RuntimeIdentifier participates in PublishRelease evaluation without requiring the Windows Desktop SDK on non-Windows CI agents. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 197b8427-6bab-4831-aefa-59ffa3dcab46
92e3a9a to
a18b262
Compare
JeremyKuhne
left a comment
There was a problem hiding this comment.
One blocking correctness issue: the Native AOT direct-compilation recovery can replay the full command through managed CLI after observable work has begun.
Note
This review feedback was generated with GitHub Copilot from local code inspection and an executed dn reproduction.
|
|
||
| if (IsAotBuild) | ||
| { | ||
| return ThrowManagedFallback(GetFullMSBuildFallbackReason()); |
There was a problem hiding this comment.
In the AOT build, CSharpCompilerCommand.Execute can return fallbackToNormalBuild=true for:
- compiler output containing
CS0006 - no compiler-server response
- an unexpected compiler-server response
By that point this invocation has already crossed the fallback commit point:
BuildStartedmay have printed the user-visible “Building...” message.MarkBuildStarthas writtenbuild-start.cache.PrepareAuxiliaryFilesmay have writtencsc.rsp, generated sources, apphost, and runtimeconfig.- The compiler server has been invoked and may have produced diagnostics.
The code then changes the level to BuildLevel.All and, under CLI_AOT, throws CommandNotAvailableInAotException. NativeEntryPoint catches that exception and runs the entire original command again through managed dotnet.dll.
I reproduced this through the real Release dn host using cached CSC arguments containing a missing reference. The AOT invocation printed the CS0006 diagnostic and fallback message, then managed replay observed the AOT-written start marker as newer than the success marker and treated it as a previous failed build. This can duplicate output and work, and the first execution's partial cache state changes the behavior of the replay.
Please split recovery into pre-commit and post-commit cases:
- Before
BuildStarted,MarkBuildStart, orCSharpCompilerCommand.Execute, preflight conditions that can be known in advance, particularly missing path-bearing inputs in replayed CSC arguments. If full MSBuild is required, request managed fallback there. - Once direct compilation begins, do not throw
CommandNotAvailableInAotException. A compiler-server transport failure should be recovered within the same invocation, such as by invoking the SDK'scsc.dllwith the prepared response file. If recovery cannot succeed, return that invocation's failure rather than replaying the command. - Preserve the existing managed behavior: managed
dotnetmay still continue from CSC to its in-process full-MSBuild path because that is one invocation, not host-level replay.
Moving MarkBuildStart below Execute, suppressing the marker, or buffering one message is insufficient: auxiliary files, compiler execution, and diagnostics are already observable.
Please add regression coverage that proves:
- A missing cached compiler input falls back before output or cache/file mutation.
- A compiler-server failure after commit does not enter
ManagedHost.RunApp. - The successful direct-compile path remains AOT-handled and writes its success cache exactly once.
If feature-preserving recovery is too large for this PR, the conservative fix is to make AOT request managed fallback whenever the selected build level is Csc, before BuildStarted. That temporarily gives up AOT fresh/changed-file compilation, but it preserves cached launches and the newly enabled physical MSBuild commands without introducing replay-after-commit behavior.
JeremyKuhne
left a comment
There was a problem hiding this comment.
There is a potential issue with the cache getting messed up and replayed, see the inline comment with more details.
There aren't any tests that actually exercise the physical commands end to end in AOT.
Double check the sizes you're reporting, I got larger ones locally.
Note that tests aren't actually running in the CI. #55854 should fix that once that is.
|
Found another potential blocker: dotnet/msbuild#14699 may lead to us wanting to remove the environment-variables that the CLI sets for the MSBuild SDK root, extensions path, etc - so that the MSBuild engine can handle the location and be safe in nested-dotnet-invocation scenarios. However, if we do that we suspect that this location is in part based on AppContext.BaseDirectory, which we know is not valid in NAOT-library scenarios like the NAOT dotnet CLI. So we'd need to design an API to allow NAOT-library callers at minimum to specify these toolset locations/information. |
Summary
pack,publish,build,restore,clean, andmsbuildin the Native AOT CLIParent PR #55441, which contains the infrastructure only, is merged into
main; this PR activates the resolvers and commands. The remaining command-layer trim/AOT dependency warnings have a dedicated tracking issue; the merged infrastructure publish is warning-free.Size and performance tradeoffs
Native image size
The current PR base (
e86710e620) and head (fa38bc8af8) were built side-by-side for Windows x64 through the repository build entry point withbuild.cmd -c Release -a x64.The size optimization now in
mainreduced the measured PR growth by about 5.25 MiB compared with the previous current-tip measurement (+23.998 MiB).SizoScope accounts for 17.6 MB of growth. The largest contributors are shared/transitive closure rather than direct command code: System.Private.CoreLib (+6.3 MB), System.Text.Json (+843.6 kB), NuGet.Protocol (+795.0 kB), Microsoft.Build (+747.8 kB), System.Linq (+705.5 kB), System.Text.Encoding.CodePages (+668.7 kB), System.Data.Common (+504.3 kB), System.Linq.Expressions (+424.7 kB), and Newtonsoft.Json (+411.4 kB). Direct
dotnet-aotcode grows by about 119.7 kB.Validation
src/Cli/dotnet/dotnet.csprojRelease build passedsrc/Cli/dotnet-aot/dotnet-aot.csprojRelease build passedProjectCompletionsEvaluateCurrentProject: 1 passedMSBuildEvaluationTests: 14 passed