You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AOT publish includes satellite assemblies in publish folder #124191
Publishing an AOT app will include satellite resource assemblies (for example <language>\AppName.resources.dll in the output folder. It appears that these are also embedded in the NativeAOT executable, the app can still show localized strings even if these are deleted.
Ideally if these satellite assemblies are not needed, they should not be copied to the publish folder. As it is, it's confusing and makes it look like they need to be deployed with the app.
To Reproduce
Create a console app
Set PublishAot to true in the .csproj file
Add a resx file and a localized resx file with a string resource in them (for example Strings.resx and Strings.es.resx)
Publish the app
Expected: No language subfolders and satellite assemblies in the publish folder
Actual: Language subfolders with satellite assemblies are present in the publish folder
I gave this problem to Copilot CLI equipped with the viktorhofer/dotnet-skills plugin, and here was its analysis after publishing + inspecting the binlog:
Root Cause Analysis
The satellite assemblies (e.g. es\AppName.resources.dll) end up in the NativeAOT publish output because the NativeAOT build integration correctly embeds them into the native binary but fails to remove them from the publish file list, so the SDK's generic publish pipeline copies them to the output directory anyway.
How satellite assemblies flow through the pipeline
Step 1: NativeAOT collects satellite assemblies for embedding
_SatelliteAssembliesToPublish = satellite assemblies from package/project references (extracted from _ResolvedCopyLocalPublishAssets by ComputeManagedAssembliesToCompileToNative)
IntermediateSatelliteAssembliesWithTargetPath = the project's own satellite assemblies (e.g. es\52913-resx-in-nativeaot.resources.dll)
These are passed to ILC via --satellite: in Microsoft.NETCore.Native.targets, which embeds them into the native binary. This part works correctly — the app can resolve localized strings even if the satellite DLLs are deleted from disk.
Step 2: ComputeLinkedFilesToPublish cleans up the publish list — but misses the project's own satellites
ComputeLinkedFilesToPublish runs BeforeTargets="ComputeResolvedFilesToPublishList" and modifies the publish list:
This successfully removes package-reference satellite assemblies (via _AssembliesToSkipPublish) and replaces the managed assembly with the native binary. But it does NOT remove IntermediateSatelliteAssembliesWithTargetPath.
Step 3: The SDK unconditionally re-adds the project's satellite assemblies to publish
Since IntermediateSatelliteAssembliesWithTargetPath was never cleared, the project's own satellite assemblies get added to ResolvedFileToPublish and are copied to the publish directory — even though they've already been embedded into the native binary.
Note that this same target does have a NativeAOT-aware condition for the runtime config file (line 525):
Condition="'$(GenerateRuntimeConfigurationFiles)' == 'true' and '$(PublishAot)' != 'true'"
Activity
baronfel commentedon Feb 9, 2026
I gave this problem to Copilot CLI equipped with the viktorhofer/dotnet-skills plugin, and here was its analysis after publishing + inspecting the binlog:
Root Cause Analysis
The satellite assemblies (e.g.
es\AppName.resources.dll) end up in the NativeAOT publish output because the NativeAOT build integration correctly embeds them into the native binary but fails to remove them from the publish file list, so the SDK's generic publish pipeline copies them to the output directory anyway.How satellite assemblies flow through the pipeline
Step 1: NativeAOT collects satellite assemblies for embedding
In
Microsoft.NETCore.Native.Publish.targets(dotnet/runtime),_ComputeIlcCompileInputsgathers satellite assemblies from two sources:_SatelliteAssembliesToPublish= satellite assemblies from package/project references (extracted from_ResolvedCopyLocalPublishAssetsbyComputeManagedAssembliesToCompileToNative)IntermediateSatelliteAssembliesWithTargetPath= the project's own satellite assemblies (e.g.es\52913-resx-in-nativeaot.resources.dll)These are passed to ILC via
--satellite:inMicrosoft.NETCore.Native.targets, which embeds them into the native binary. This part works correctly — the app can resolve localized strings even if the satellite DLLs are deleted from disk.Step 2:
ComputeLinkedFilesToPublishcleans up the publish list — but misses the project's own satellitesComputeLinkedFilesToPublishrunsBeforeTargets="ComputeResolvedFilesToPublishList"and modifies the publish list:This successfully removes package-reference satellite assemblies (via
_AssembliesToSkipPublish) and replaces the managed assembly with the native binary. But it does NOT removeIntermediateSatelliteAssembliesWithTargetPath.Step 3: The SDK unconditionally re-adds the project's satellite assemblies to publish
In
Microsoft.NET.Publish.targets(dotnet/sdk),ComputeResolvedFilesToPublishListunconditionally includes:Since
IntermediateSatelliteAssembliesWithTargetPathwas never cleared, the project's own satellite assemblies get added toResolvedFileToPublishand are copied to the publish directory — even though they've already been embedded into the native binary.Note that this same target does have a NativeAOT-aware condition for the runtime config file (line 525):
Suggested fix
The
ComputeLinkedFilesToPublishtarget inMicrosoft.NETCore.Native.Publish.targetsshould also clear the project's intermediate satellite assemblies:This mirrors the pattern already used for
IntermediateAssemblyand_DebugSymbolsIntermediatePathin the same target.don't set invariant globalzn - resource copy is an aot bug https://gi…
dotnet-policy-service commentedon Feb 9, 2026
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.
Fix NativeAOT publish including satellite assemblies despite embeddin…