Skip to content

Skip full Build for AOT publish, use Compile instead#54515

Open
marcpopMSFT wants to merge 2 commits into
mainfrom
marcpopMSFT-noimplicitbuildonpublish
Open

Skip full Build for AOT publish, use Compile instead#54515
marcpopMSFT wants to merge 2 commits into
mainfrom
marcpopMSFT-noimplicitbuildonpublish

Conversation

@marcpopMSFT
Copy link
Copy Markdown
Member

When publishing with PublishAot=true, the implicit Build step was producing a full self-contained managed deployment (apphost, DLLs, deps.json, runtimeconfig, runtime pack files) in the output directory. This output is completely unused by the AOT pipeline, which reads from @(IntermediateAssembly) in obj, not from bin\ output.

This change introduces _PublishAotBuildAlternative that runs Compile (plus resource and satellite assembly targets) instead of full Build for AOT publish. This eliminates the confusing managed artifacts from the output directory while preserving all AOT publish functionality.

The target list for AOT publish is:

  • BuildOnlySettings: configures build-time settings
  • PrepareForBuild: creates output directories
  • PrepareResources: compiles .resx to .resources files
  • Compile: produces IL assembly in obj\ (includes ResolveReferences)
  • CreateSatelliteAssemblies: generates culture-specific resource DLLs

When publishing with PublishAot=true, the implicit Build step was producing
a full self-contained managed deployment (apphost, DLLs, deps.json,
runtimeconfig, runtime pack files) in the output directory. This output is
completely unused by the AOT pipeline, which reads from @(IntermediateAssembly)
in obj\, not from bin\ output.

This change introduces _PublishAotBuildAlternative that runs Compile (plus
resource and satellite assembly targets) instead of full Build for AOT
publish. This eliminates the confusing managed artifacts from the output
directory while preserving all AOT publish functionality.

The target list for AOT publish is:
- BuildOnlySettings: configures build-time settings
- PrepareForBuild: creates output directories
- PrepareResources: compiles .resx to .resources files
- Compile: produces IL assembly in obj\ (includes ResolveReferences)
- CreateSatelliteAssemblies: generates culture-specific resource DLLs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 29, 2026 20:36
@marcpopMSFT marcpopMSFT requested review from a team as code owners May 29, 2026 20:36
Comment on lines +167 to +172
Condition="'$(NoBuild)' != 'true' and '$(PublishAot)' != 'true'"
DependsOnTargets="Build;$(_CorePublishTargets)" />

<Target Name="_PublishAotBuildAlternative"
Condition="'$(NoBuild)' != 'true' and '$(PublishAot)' == 'true'"
DependsOnTargets="$(_PublishAotBuildAlternativeDependsOn)" />
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would this logic/split be the same for apps that are merely trimmed too? They are similarly platform-specific and just need the primary output dlls.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

copilot agrees with you but thinks we should start small: I'd recommend keeping this PR focused on AOT only. The same pattern applies to PublishTrimmed, PublishReadyToRun, and PublishSingleFile, but those have broader usage and more interaction surface. Better to validate AOT first, then extend in a follow-up PR.

It seems to be worried about the impact changing the others would have.

Copy link
Copy Markdown
Contributor

Copilot AI left a 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 changes Native AOT publish so it compiles the intermediate IL needed by the AOT pipeline without running the full Build target, avoiding unused managed self-contained artifacts in bin output.

Changes:

  • Adds an AOT-specific publish build alternative in Microsoft.NET.Publish.targets.
  • Routes PublishAot=true publishes through Compile/resource targets instead of full Build.
  • Updates and adds Native AOT publish tests for clean output and project-reference publishing.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets Adds _PublishAotBuildAlternative and excludes AOT publish from the normal full-build path.
test/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs Updates property-recording hooks for skipped Build and adds Native AOT publish regression tests.

@(IntermediateAssembly) in obj\, not from bin\ output. Skipping Build avoids producing
unnecessary self-contained managed output (apphost, deps.json, runtimeconfig, runtime
pack files) in the output directory that would confuse users and automation. -->
<_BeforePublishAotBuildTargets Condition="'$(PublishAot)' == 'true'">
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There's a part of me that thinks that we could make this even better if we didn't call these targets on this project instance - instead, if we could set up targets that called this chain on 'this project instance with RuntimeIdentifier' removed, you'd get almost all of the way to an 'agnostic' build with 'platform-specific' publish steps.

…mentation

- Add UseAotOptimizedPublish property (default true for PublishAot) as opt-out
  to restore old Build behavior during AOT publish
- Improve test to verify runtime pack files (System.Private.CoreLib.dll,
  coreclr.dll) are not present in build output directory
- Add publish-build-optimization.md documenting the breaking change,
  all publish modes, opt-out mechanism, and future work

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants