From 05bd1e4b690ff0616fbf75326d0df8d9d6770046 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Feb 2026 16:58:35 +0000 Subject: [PATCH 1/3] Initial plan From 275674968bae20f1ee79f5b8e4a896456e8ef395 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Feb 2026 17:23:13 +0000 Subject: [PATCH 2/3] Decouple ILLink managed assembly computation from ComputeIlcCompileInputs Co-authored-by: sbomer <787361+sbomer@users.noreply.github.com> --- .../nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index e758f681c3c0ee..8b68c7b1e903d4 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -124,7 +124,7 @@ The .NET Foundation licenses this file to you under the MIT license. Condition="'$(NativeCompilationDuringPublish)' == 'true'"> - + From a5cee7cf23b23e46a8719bff986b7cdef008fc3d Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 25 Feb 2026 11:51:05 -0800 Subject: [PATCH 3/3] Derive ILC inputs from ResolvedFileToPublish instead of ManagedAssemblyToLink Factor _PrepareTrimConfiguration out of PrepareForILLink so shared trim configuration operates on ResolvedFileToPublish and flows to both ILLink and ILC without duplication. For NativeAOT, _ComputeAssembliesToCompileToNative replaces CoreCLR runtime pack files with DefaultFrameworkAssemblies (tagged PostprocessAssembly=true) before _PrepareTrimConfiguration runs. _ComputeIlcCompileInputs then derives IlcReference from ResolvedFileToPublish via PostprocessAssembly metadata, ensuring ILC sees ILLink-relocated paths when both run. ComputeLinkedFilesToPublish hooks AfterTargets=ILLink (instead of ComputeResolvedFilesToPublishList) for correct ordering when both ILLink and ILC run. RunILLink is made conditional so projects can opt in. Remove ManagedAssemblies output from the C# task (replaced by ResolvedFileToPublish filtering). Add RuntimePackFilesToSkipPublish output for early removal of CoreCLR runtime pack files. Fix OOB assembly handling so overrides stay in ResolvedFileToPublish. --- .../Microsoft.NETCore.Native.Publish.targets | 38 ++++--- .../Microsoft.NETCore.Native.targets | 24 ++--- ...mputeManagedAssembliesToCompileToNative.cs | 45 +++----- .../build/Microsoft.NET.ILLink.targets | 102 +++++++++++------- 4 files changed, 109 insertions(+), 100 deletions(-) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets index c31ed57ee902da..6de6bf53f99454 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Publish.targets @@ -2,9 +2,11 @@ + DependsOnTargets="$(IlcDynamicBuildPropertyDependencies);_ComputeAssembliesToCompileToNative;_PrepareTrimConfiguration"> + - + <_IlcManagedInputAssemblies Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.PostprocessAssembly)' == 'true'" /> + @@ -14,14 +16,16 @@ This target hooks into the dotnet CLI publish pipeline. That pipeline has a target called ComputeFilesToPublish which produces the ItemGroup ResolvedFileToPublish. We modify this item group to control what gets - published after NativeAOT optimizes the application. + published after NativeAOT optimizes the application. Hooks after ILLink, + which runs after ComputeResolvedFilesToPublishList, to ensure correct + ordering for scenarios that run both. --> - + @@ -29,8 +33,6 @@ $(NativeBinaryPrefix)$(TargetName)$(NativeBinaryExt) PreserveNewest - - @@ -60,13 +62,14 @@ - + @@ -104,11 +107,18 @@ SdkAssemblies="@(PrivateSdkAssemblies)" FrameworkAssemblies="@(FrameworkAssemblies)"> - - + + + + + + true + + + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 8b68c7b1e903d4..33664c250d44fa 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -27,7 +27,7 @@ The .NET Foundation licenses this file to you under the MIT license. false true true - false + false $(TreatWarningsAsErrors) <_IsiOSLikePlatform Condition="'$(_targetOS)' == 'maccatalyst' or $(_targetOS.StartsWith('ios')) or $(_targetOS.StartsWith('tvos'))">true <_IsApplePlatform Condition="'$(_targetOS)' == 'osx' or '$(_IsiOSLikePlatform)' == 'true'">true @@ -101,7 +101,6 @@ The .NET Foundation licenses this file to you under the MIT license. Compile;ComputeIlcCompileInputs $(IlcCompileDependsOn);BuildFrameworkLib $(IlcCompileDependsOn);SetupOSSpecificProps - $(IlcCompileDependsOn);PrepareForILLink @@ -119,15 +118,6 @@ The .NET Foundation licenses this file to you under the MIT license. - - - - - - - @@ -170,7 +160,6 @@ The .NET Foundation licenses this file to you under the MIT license. - @@ -200,13 +189,12 @@ The .NET Foundation licenses this file to you under the MIT license. DependsOnTargets="$(IlcCompileDependsOn)"> - <_IlcRootedAssembliesRaw Include="@(TrimmerRootAssembly)" Condition="%(TrimmerRootAssembly.RootMode) != 'EntryPoint'" /> - <_IlcRootedAssembliesRaw Include="@(ManagedAssemblyToLink)" Condition="%(ManagedAssemblyToLink.TrimMode) == 'copy'" /> - <_IlcConditionallyRootedAssembliesRaw Include="@(ManagedAssemblyToLink)" Condition="%(ManagedAssemblyToLink.TrimMode) == 'copyused'" /> - <_IlcTrimmedAssembliesRaw Include="@(ManagedAssemblyToLink)" Condition="%(ManagedAssemblyToLink.TrimMode) == 'link'" /> - <_IlcSingleWarnAssembliesRaw Include="@(ManagedAssemblyToLink)" Condition="%(ManagedAssemblyToLink.TrimmerSingleWarn) == 'true'" /> - <_IlcNoSingleWarnAssembliesRaw Include="@(ManagedAssemblyToLink)" Condition="%(ManagedAssemblyToLink.TrimmerSingleWarn) == 'false'" /> + <_IlcRootedAssembliesRaw Include="@(_IlcManagedInputAssemblies)" Condition="%(_IlcManagedInputAssemblies.TrimMode) == 'copy'" /> + <_IlcConditionallyRootedAssembliesRaw Include="@(_IlcManagedInputAssemblies)" Condition="%(_IlcManagedInputAssemblies.TrimMode) == 'copyused'" /> + <_IlcTrimmedAssembliesRaw Include="@(_IlcManagedInputAssemblies)" Condition="%(_IlcManagedInputAssemblies.TrimMode) == 'link'" /> + <_IlcSingleWarnAssembliesRaw Include="@(_IlcManagedInputAssemblies)" Condition="%(_IlcManagedInputAssemblies.TrimmerSingleWarn) == 'true'" /> + <_IlcNoSingleWarnAssembliesRaw Include="@(_IlcManagedInputAssemblies)" Condition="%(_IlcManagedInputAssemblies.TrimmerSingleWarn) == 'false'" /> diff --git a/src/coreclr/tools/aot/ILCompiler.Build.Tasks/ComputeManagedAssembliesToCompileToNative.cs b/src/coreclr/tools/aot/ILCompiler.Build.Tasks/ComputeManagedAssembliesToCompileToNative.cs index 6ed14b4e3e25c4..19d435e2303422 100644 --- a/src/coreclr/tools/aot/ILCompiler.Build.Tasks/ComputeManagedAssembliesToCompileToNative.cs +++ b/src/coreclr/tools/aot/ILCompiler.Build.Tasks/ComputeManagedAssembliesToCompileToNative.cs @@ -74,13 +74,6 @@ public string DotNetHostPolicyLibraryName set; } - [Output] - public ITaskItem[] ManagedAssemblies - { - get; - set; - } - [Output] public ITaskItem[] SatelliteAssemblies { @@ -88,8 +81,12 @@ public ITaskItem[] SatelliteAssemblies set; } + /// + /// CoreCLR runtime pack files (apphost, native assets, managed assemblies replaced by NativeAOT equivalents) + /// that should be removed from the publish output and replaced with NativeAOT runtime pack assemblies. + /// [Output] - public ITaskItem[] AssembliesToSkipPublish + public ITaskItem[] RuntimePackFilesToSkipPublish { get; set; @@ -97,8 +94,7 @@ public ITaskItem[] AssembliesToSkipPublish public override bool Execute() { - var list = new List(); - var assembliesToSkipPublish = new List(); + var runtimePackFilesToSkipPublish = new List(); var satelliteAssemblies = new List(); var nativeAotFrameworkAssembliesToUse = new Dictionary(); @@ -126,7 +122,7 @@ public override bool Execute() // Skip the native apphost (whose name ends up colliding with the native output binary) and supporting libraries if (itemSpec.EndsWith(DotNetAppHostExecutableName, StringComparison.OrdinalIgnoreCase) || itemSpec.Contains(DotNetHostFxrLibraryName) || itemSpec.Contains(DotNetHostPolicyLibraryName)) { - assembliesToSkipPublish.Add(taskItem); + runtimePackFilesToSkipPublish.Add(taskItem); continue; } @@ -135,7 +131,7 @@ public override bool Execute() && !assemblyFileName.EndsWith(".dex", StringComparison.OrdinalIgnoreCase)) { // Skip the native components of the runtime pack, we don't need them for NativeAOT. - assembliesToSkipPublish.Add(taskItem); + runtimePackFilesToSkipPublish.Add(taskItem); continue; } @@ -148,8 +144,10 @@ public override bool Execute() if (!isFromRuntimePack) { // The assembly was overridden by an OOB package through standard .NET SDK conflict resolution. - // Use that version instead of swapping to the NativeAOT one. - list.Add(taskItem); + // Don't swap to the NativeAOT version; the user's version stays in + // ResolvedFileToPublish and will be picked up as an ILC input via + // its PostprocessAssembly=true metadata. + continue; } else if (assemblyFileName == "System.Private.CoreLib.dll" && GetFileVersion(itemSpec).CompareTo(GetFileVersion(frameworkItem.ItemSpec)) > 0) { @@ -158,7 +156,7 @@ public override bool Execute() Log.LogError($"Overriding System.Private.CoreLib.dll with a newer version is not supported. Attempted to use {itemSpec} instead of {frameworkItem.ItemSpec}."); } - assembliesToSkipPublish.Add(taskItem); + runtimePackFilesToSkipPublish.Add(taskItem); continue; } @@ -170,9 +168,8 @@ public override bool Execute() continue; } - // For all other files, check if they are managed assemblies. - // If they're managed, skip publishing them and categorize them correctly as inputs to ILC. - // If they're not managed assemblies, then they're native dependencies. Allow them to be published. + // Check if this is a satellite assembly by reading its culture metadata. + // Non-managed files are silently skipped as a safety measure. try { using (FileStream moduleStream = File.OpenRead(itemSpec)) @@ -185,14 +182,7 @@ public override bool Execute() { string culture = moduleMetadataReader.GetString(moduleMetadataReader.GetAssemblyDefinition().Culture); - assembliesToSkipPublish.Add(taskItem); - - // Split satellite assemblies from normal assemblies - if (culture == "" || culture.Equals("neutral", StringComparison.OrdinalIgnoreCase)) - { - list.Add(taskItem); - } - else + if (culture != "" && !culture.Equals("neutral", StringComparison.OrdinalIgnoreCase)) { satelliteAssemblies.Add(taskItem); } @@ -205,8 +195,7 @@ public override bool Execute() } } - ManagedAssemblies = list.ToArray(); - AssembliesToSkipPublish = assembliesToSkipPublish.ToArray(); + RuntimePackFilesToSkipPublish = runtimePackFilesToSkipPublish.ToArray(); SatelliteAssemblies = satelliteAssemblies.ToArray(); return true; diff --git a/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets b/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets index 16198390f88f7b..7812d9f85bd45e 100644 --- a/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets +++ b/src/tools/illink/src/ILLink.Tasks/build/Microsoft.NET.ILLink.targets @@ -193,11 +193,71 @@ Copyright (c) .NET Foundation. All rights reserved. + + + + + + full + + + + true + + + + + + + + + + + <__SingleWarnIntermediateAssembly Include="@(ResolvedFileToPublish)" /> + <__SingleWarnIntermediateAssembly Remove="@(IntermediateAssembly)" /> + + <_SingleWarnIntermediateAssembly Include="@(ResolvedFileToPublish)" /> + <_SingleWarnIntermediateAssembly Remove="@(__SingleWarnIntermediateAssembly)" /> + + <_SingleWarnIntermediateAssembly> + false + + + + + + + + false + + + + + <_TrimmerFeatureSettings Include="@(RuntimeHostConfigurationOption)" Condition="'%(RuntimeHostConfigurationOption.Trim)' == 'true'" /> + + + + - - full - - $(TreatWarningsAsErrors) - true @@ -281,38 +335,6 @@ Copyright (c) .NET Foundation. All rights reserved. - - - - - - - - - <__SingleWarnIntermediateAssembly Include="@(ManagedAssemblyToLink)" /> - <__SingleWarnIntermediateAssembly Remove="@(IntermediateAssembly)" /> - - <_SingleWarnIntermediateAssembly Include="@(ManagedAssemblyToLink)" /> - <_SingleWarnIntermediateAssembly Remove="@(__SingleWarnIntermediateAssembly)" /> - - <_SingleWarnIntermediateAssembly> - false - - - - - - - - false - - - - - <_TrimmerFeatureSettings Include="@(RuntimeHostConfigurationOption)" Condition="'%(RuntimeHostConfigurationOption.Trim)' == 'true'" /> - - - +