Conversation
Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/43b9b3d5-da9c-475f-9496-f58388261d7f Co-authored-by: sbomer <787361+sbomer@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix satellite assembly handling in SDK publishing
Fix NativeAOT: pass package satellite assemblies to ILC and remove them from publish output
Apr 17, 2026
Contributor
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes NativeAOT publish handling of satellite resource assemblies from NuGet packages by ensuring they’re passed to ILC for embedding (via --satellite:) and removed from publish output so they don’t leak as loose .resources.dll files.
Changes:
- Populate
IlcSatelliteAssemblyfrom@(ResolvedFileToPublish)whereAssetType == resources(package satellites) in addition to project satellites from@(IntermediateSatelliteAssembliesWithTargetPath). - Remove satellites from
@(ResolvedFileToPublish)using the unified@(IlcSatelliteAssembly)list (covers both package + project satellites). - Simplify
ComputeManagedAssembliesToCompileToNativeby removing the deadSatelliteAssembliesoutput and PE-based classification logic/usings.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/coreclr/tools/aot/ILCompiler.Build.Tasks/ComputeManagedAssembliesToCompileToNative.cs | Removes unused satellite-assembly detection/output logic that no longer matches the SDK’s metadata contract. |
| src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets | Correctly identifies package satellite assemblies via AssetType=resources, passes them to ILC, and prunes them from publish output. |
This was referenced Apr 18, 2026
Open
MichalStrehovsky
approved these changes
Apr 20, 2026
Member
MichalStrehovsky
left a comment
There was a problem hiding this comment.
LGTM assuming you tried it and it works now.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
NativeAOT publish was leaking satellite
.dllfiles from NuGet packages into the publish directory and failing to pass them to ILC via--satellite:(required for resource embedding at link time).Root cause:
ComputeManagedAssembliesToCompileToNativeclassified satellites by PE-inspecting items flaggedPostprocessAssembly=true. The SDK never sets this metadata on resource items (AssetType=resources), so the satellite branch was dead code —SatelliteAssembliesoutput was always empty. PR #111514 introduced this regression; PR #124192 partially fixed project-own satellites viaIntermediateSatelliteAssembliesWithTargetPathbut left the package case broken.Changes
Microsoft.NETCore.Native.Publish.targetsIlcSatelliteAssemblyviaCondition="'%(ResolvedFileToPublish.AssetType)' == 'resources'"(package satellites) in addition to the existingIntermediateSatelliteAssembliesWithTargetPath(project satellites)Remove="@(IntermediateSatelliteAssembliesWithTargetPath)"withRemove="@(IlcSatelliteAssembly)"so both package and project satellites are pruned fromResolvedFileToPublish<Output TaskParameter="SatelliteAssemblies" ...>wire-upComputeManagedAssembliesToCompileToNative.csSatelliteAssemblies[Output]property, PE-reading culture classification loop,PostprocessAssemblyguard block, and the now-unusedSystem.Reflection.Metadata/System.Reflection.PortableExecutableusings (~45 lines removed, none of it ever ran)Customer Impact
NativeAOT apps that reference NuGet packages containing satellite assemblies (e.g.
System.CommandLine) would fail to resolve localized resources at runtime and would have stray.dllfiles in the publish output, defeating the single-file native binary guarantee.Regression
Yes — regressed in PR #111514 ("Run ILC after ComputeResolvedFilesToPublishList"). PR #124192 closed the gap for project-own satellites but missed package satellites.
Testing
End-to-end validated with a repro app (
PublishAot=true,System.CommandLine 2.0.6package dependency, projectStrings.resx+Strings.es.resx): publish output is clean (only native binary + debug symbols), ILC receives the expected--satellite:arguments for all cultures, and runtime correctly resolveses/de/jaresources from both package and project sources.Risk
Low. The targets change is purely additive for the satellite item population and replaces a narrower
Removewith a broader one that is a strict superset of the previous behavior. The task change removes code that was provably never executed under the current SDK contract.Package authoring no longer needed in .NET 9
IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.
Original prompt
Chronological review: 1. User asked to read dotnet/runtime PR #124192 + related SDK issue comments 2. Asked for a repro in /tmp 3. Asked to root cause 4. Asked for logging / both app and package resources in repro 5. Asked about runtime behavior 6. Asked how SDK populates ResolvedFileToPublish 7. Asked what gets passed as --satellite 8. Asked to fix 9. Asked if I tested 10. Asked about task's satellite filtering being moot → led to cleanup 11. Asked about `_IlcReferenceSatelliteAssemblies` naming → kept (consistency) 12. Then asked: "What if we consider IlcSatelliteAssembly to be the snapshot?" → simplified to inline include + `Remove="@(IlcSatelliteAssembly)"` 13. Asked to remove two comments 14. Asked to re-test 15. Asked to commit → committed as `e765e126dcb` 16. Most recent: asked "Why weren't we passing satellites, did that regress at some point?" → I investigated git history, found PR #111514 was the regression point.Recent commands and results:
git log --oneline --all -S 'SatelliteAssemblies'on task file → found b134fa2 (Implement resource lookup in satellite assemblies #86689, 2023, MichalStrehovsky, original satellite support)git show b134fa28352→ showed original implementation: task read ALL items, PE-inspected, classified by Culturegit log --oneline --all -S 'PostprocessAssembly'→ found e144870 "Skip non-PostprocessAssembly files..." (Feb 17 2026) and a5cee7c "Derive ILC inputs from ResolvedFileToPublish..." (Feb 25 2026), both by Sven Boemergit log --all --oneline --ancestry-path→ showed these were part of branch ilc-compile-order / ilcPublishgit log main --grep='Run ILC after'→ confirmed squash-merged as44e21b71149 Run ILC after ComputeResolvedFilesToPublishList (#111514)Final answer given: PR #111514 regressed satellite passing. Original PR #86689 (2023) worked. PR #124192 partially fixed project-own case. This commit closes package case.
Commit created: e765e126dcb on branch satellite-fix, not pushed.
1. Conversation Overview: - Primary Objectives: Investigate dotnet/runtime PR #124192 / dotnet/sdk#53422 regression where NativeAOT publish leaks package satellite `.dll` files AND fails to embed them via ILC. Root-cause, fix, validate, commit. - Session Context: Progressed through reading comments → repro → root cause → logging → SDK trace → fix implementation → code review/cleanup iterations → test → commit → regression history. - User Intent Evolution: From fixing the surface bug to cleaning up dead code, then simplifying the fix (inlining `IlcSatelliteAssembly` as the snapshot), then historical attribution.-
- .NET 11 preview 3 SDK (
- NativeAOT publish pipeline:
- SDK
- Package/ref satellites land in
-
- Changed
- Changed
- Dropped
- Removed
- Net −45 lines; +3/−3 on targets file
- Repro at
-
- Root cause: Task's classification logic gated on
- Fix: Classify via
- Dead code cleanup: task's
-
- Completed: investigation, repro, fix, cleanup, end-to-end val...
Technical Foundation:
11.0.100-preview.3.26172.108) pinned via global.json in the repro_ComputeIlcCompileInputs→NativeCompile(post PR Use SDK NativeCompile hook for ILC publish integration #125629 at HEAD) /ComputeLinkedFilesToPublish(pre Use SDK NativeCompile hook for ILC publish integration #125629 in installed SDK)_ComputeAssembliesToPostprocessOnPublishdeliberately excludes satellites fromPostprocessAssembly=truemetadataResolvedFileToPublishwithAssetType=='resources'; project's own satellites arrive viaIntermediateSatelliteAssembliesWithTargetPathIlcSatelliteAssemblyitem →--satellite:ILC args (required for embedding; NAOT can't load from disk)Codebase Status:
/home/sven/src/satellite-fix/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets:<IlcSatelliteAssembly Include="@(_SatelliteAssembliesToPublish)" />to<IlcSatelliteAssembly Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.AssetType)' == 'resources'" /><ResolvedFileToPublish Remove="@(IntermediateSatelliteAssembliesWithTargetPath)" />to<ResolvedFileToPublish Remove="@(IlcSatelliteAssembly)" /><Output TaskParameter="SatelliteAssemblies" ItemName="_SatelliteAssembliesToPublish" />/home/sven/src/satellite-fix/src/coreclr/tools/aot/ILCompiler.Build.Tasks/ComputeManagedAssembliesToCompileToNative.cs:SatelliteAssemblies[Output]property, PE-reading culture classification,PostprocessAssemblylate-filter check,System.Reflection.Metadata/PortableExecutableusings/tmp/aot-satellite-repro/app/with diagnostic dump targets,PublishAot=true,System.CommandLine 2.0.6,Strings.resx+Strings.es.resxProblem Resolution:
PostprocessAssembly=truewhich SDK never sets on satellites, making satellite branch unreachableAssetType=='resources'in MSBuild directly; useIlcSatelliteAssemblyas snapshot consumed by both ILC and theResolvedFileToPublishremoveSatelliteAssembliesoutput never produced anything under current SDK contractProgress Tracking:
Adding a test for this in dotnet/sdk#53971.
Created from Copilot CLI via the copilot delegate command.