diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs
index 9ec56c965a8b..9447c16cbd02 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs
@@ -99,7 +99,10 @@ public class ProcessFrameworkReferences : TaskBase
public ITaskItem[] Crossgen2Packs { get; set; }
[Output]
- public ITaskItem[] ILCompilerPacks { get; set; }
+ public ITaskItem[] HostILCompilerPacks { get; set; }
+
+ [Output]
+ public ITaskItem[] TargetILCompilerPacks { get; set; }
// Runtime packs which aren't available for the specified RuntimeIdentifier
[Output]
@@ -617,7 +620,29 @@ private bool AddAotOrR2RRuntimePackage(AotPackageType packageType, Version norma
}
else
{
- ILCompilerPacks = new[] { newItem };
+ HostILCompilerPacks = new[] { newItem };
+ // ILCompiler supports cross target compilation. If there is a cross-target request, we need to download that package as well
+ // We expect RuntimeIdentifier to be defined during publish but can allow during build
+ if (RuntimeIdentifier != null)
+ {
+ var targetRuntimeIdentifier = NuGetUtils.GetBestMatchingRid(runtimeGraph, RuntimeIdentifier, packSupportedRuntimeIdentifiers, out bool wasInGraph2);
+ if (targetRuntimeIdentifier == null)
+ {
+ return false;
+ }
+ if (!hostRuntimeIdentifier.Equals(targetRuntimeIdentifier))
+ {
+ var runtimeIlcPackName = packPattern.Replace("**RID**", targetRuntimeIdentifier);
+ TaskItem targetIlcPackToDownload = new TaskItem(runtimeIlcPackName);
+ targetIlcPackToDownload.SetMetadata(MetadataKeys.Version, packVersion);
+ packagesToDownload.Add(targetIlcPackToDownload);
+
+ var newItem2 = new TaskItem(runtimeIlcPackName);
+ newItem2.SetMetadata(MetadataKeys.NuGetPackageId, runtimeIlcPackName);
+ newItem2.SetMetadata(MetadataKeys.NuGetPackageVersion, packVersion);
+ TargetILCompilerPacks = new[] { newItem2 };
+ }
+ }
}
return true;
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets
index fbfadfb41f81..df564baca1a4 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets
@@ -120,7 +120,8 @@ Copyright (c) .NET Foundation. All rights reserved.
-
+
+
@@ -252,12 +253,19 @@ Copyright (c) .NET Foundation. All rights reserved.
-
+
+
+
+
+
+
diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs
index 07b7d06f841a..c20ecbf015e8 100644
--- a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs
+++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs
@@ -78,6 +78,40 @@ public void NativeAot_hw_runs_with_no_warnings_when_PublishAot_is_enabled(string
}
}
+ [RequiresMSBuildVersionTheory("17.0.0.32901")]
+ [InlineData(ToolsetInfo.CurrentTargetFramework)]
+ public void NativeAot_hw_runs_with_no_warnings_when_PublishAot_is_false(string targetFramework)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ var projectName = "HellowWorldNativeAotApp";
+ var rid = EnvironmentInfo.GetCompatibleRid(targetFramework);
+
+ var testProject = CreateHelloWorldTestProject(targetFramework, projectName, true);
+ testProject.AdditionalProperties["PublishAot"] = "false";
+ var testAsset = _testAssetsManager.CreateTestProject(testProject);
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
+ publishCommand
+ .Execute($"/p:RuntimeIdentifier={rid}")
+ .Should().Pass()
+ .And.NotHaveStdOutContaining("IL2026")
+ .And.NotHaveStdErrContaining("NETSDK1179")
+ .And.NotHaveStdErrContaining("warning");
+
+ var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName;
+ var publishedDll = Path.Combine(publishDirectory, $"{projectName}.dll");
+ var publishedExe = Path.Combine(publishDirectory, $"{testProject.Name}{Constants.ExeSuffix}");
+
+ // PublishAot=false will be a normal publish
+ File.Exists(publishedDll).Should().BeTrue();
+
+ var command = new RunExeCommand(Log, publishedExe)
+ .Execute().Should().Pass()
+ .And.HaveStdOutContaining("Hello World");
+ }
+ }
+
[RequiresMSBuildVersionTheory("17.0.0.32901")]
[InlineData(ToolsetInfo.CurrentTargetFramework)]
public void NativeAot_app_runs_in_debug_with_no_config_when_PublishAot_is_enabled(string targetFramework)
@@ -245,7 +279,6 @@ public void NativeAot_hw_runs_with_PackageReference_PublishAot_is_enabled(string
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
testProject.AdditionalProperties["StripSymbols"] = "true";
- testProject.AdditionalProperties["ObjCopyName"] = "objcopy";
}
var testAsset = _testAssetsManager.CreateTestProject(testProject);
@@ -274,6 +307,102 @@ public void NativeAot_hw_runs_with_PackageReference_PublishAot_is_enabled(string
}
}
+ [RequiresMSBuildVersionTheory("17.0.0.32901")]
+ [InlineData(ToolsetInfo.CurrentTargetFramework)]
+ public void NativeAot_hw_runs_with_PackageReference_PublishAot_is_empty(string targetFramework)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ var projectName = "HellowWorldNativeAotApp";
+ var rid = EnvironmentInfo.GetCompatibleRid(targetFramework);
+
+ var testProject = CreateHelloWorldTestProject(targetFramework, projectName, true);
+
+ // This will add a reference to a package that will also be automatically imported by the SDK
+ testProject.PackageReferences.Add(new TestPackageReference("Microsoft.DotNet.ILCompiler", "7.0.0-*"));
+
+ // Linux symbol files are embedded and require additional steps to be stripped to a separate file
+ // assumes /bin (or /usr/bin) are in the PATH
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ testProject.AdditionalProperties["StripSymbols"] = "true";
+ }
+ var testAsset = _testAssetsManager.CreateTestProject(testProject);
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
+ publishCommand
+ .Execute($"/p:RuntimeIdentifier={rid}")
+ .Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory(targetFramework: targetFramework, runtimeIdentifier: rid).FullName;
+ var sharedLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll" : ".so";
+ var publishedDll = Path.Combine(publishDirectory, $"{projectName}{sharedLibSuffix}");
+ var publishedExe = Path.Combine(publishDirectory, $"{testProject.Name}{Constants.ExeSuffix}");
+ var symbolSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".pdb" : ".dbg";
+ var publishedDebugFile = Path.Combine(publishDirectory, $"{testProject.Name}{symbolSuffix}");
+
+ // NativeAOT published dir should not contain a non-host stand alone package
+ File.Exists(publishedDll).Should().BeFalse();
+ // The exe exist and should be native
+ File.Exists(publishedExe).Should().BeTrue();
+ File.Exists(publishedDebugFile).Should().BeTrue();
+ IsNativeImage(publishedExe).Should().BeTrue();
+
+ var command = new RunExeCommand(Log, publishedExe)
+ .Execute().Should().Pass()
+ .And.HaveStdOutContaining("Hello World");
+ }
+ }
+
+ [RequiresMSBuildVersionTheory("17.0.0.32901")]
+ [InlineData(ToolsetInfo.CurrentTargetFramework)]
+ public void NativeAot_hw_runs_with_cross_PackageReference_PublishAot_is_enabled(string targetFramework)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && (RuntimeInformation.OSArchitecture == System.Runtime.InteropServices.Architecture.X64))
+ {
+ var projectName = "HellowWorldNativeAotApp";
+ var rid = "win-arm64";
+
+ var testProject = CreateHelloWorldTestProject(targetFramework, projectName, true);
+ testProject.AdditionalProperties["PublishAot"] = "true";
+
+ // This will add a reference to a package that will also be automatically imported by the SDK
+ testProject.PackageReferences.Add(new TestPackageReference("Microsoft.DotNet.ILCompiler", "7.0.0-*"));
+ testProject.PackageReferences.Add(new TestPackageReference("runtime.win-x64.Microsoft.DotNet.ILCompiler", "7.0.0-*"));
+
+ var testAsset = _testAssetsManager.CreateTestProject(testProject);
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
+ publishCommand
+ .Execute($"/p:RuntimeIdentifier={rid}")
+ .Should().Pass();
+ }
+ }
+
+ [RequiresMSBuildVersionTheory("17.0.0.32901")]
+ [InlineData(ToolsetInfo.CurrentTargetFramework)]
+ public void NativeAot_hw_runs_with_cross_PackageReference_PublishAot_is_empty(string targetFramework)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && (RuntimeInformation.OSArchitecture == System.Runtime.InteropServices.Architecture.X64))
+ {
+ var projectName = "HellowWorldNativeAotApp";
+ var rid = "win-arm64";
+
+ var testProject = CreateHelloWorldTestProject(targetFramework, projectName, true);
+
+ // This will add a reference to a package that will also be automatically imported by the SDK
+ testProject.PackageReferences.Add(new TestPackageReference("Microsoft.DotNet.ILCompiler", "7.0.0-*"));
+ testProject.PackageReferences.Add(new TestPackageReference("runtime.win-x64.Microsoft.DotNet.ILCompiler", "7.0.0-*"));
+
+ var testAsset = _testAssetsManager.CreateTestProject(testProject);
+
+ var publishCommand = new PublishCommand(Log, Path.Combine(testAsset.TestRoot, testProject.Name));
+ publishCommand
+ .Execute($"/p:RuntimeIdentifier={rid}")
+ .Should().Pass();
+ }
+ }
+
[RequiresMSBuildVersionTheory("17.0.0.32901")]
[InlineData(ToolsetInfo.CurrentTargetFramework)]
public void Only_Aot_warnings_are_produced_if_EnableAotAnalyzer_is_set(string targetFramework)