From d14b3d534b2056cf069cb1c8eb872fb6b75c1a1b Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Sun, 14 Aug 2022 06:52:12 -0700 Subject: [PATCH 1/5] Corresponding PublishAOT changes to match the runtime cleanup changes --- .../ProcessFrameworkReferences.cs | 19 ++- ...T.Sdk.FrameworkReferenceResolution.targets | 10 +- .../GivenThatWeWantToPublishAnAotApp.cs | 132 ++++++++++++++++++ 3 files changed, 159 insertions(+), 2 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index 9ec56c965a8b..b1e832d7beda 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[] ILCompilerPacks { get; set; } + + [Output] + public ITaskItem[] ILCompilerPacks2 { get; set; } // Runtime packs which aren't available for the specified RuntimeIdentifier [Output] @@ -618,6 +621,20 @@ private bool AddAotOrR2RRuntimePackage(AotPackageType packageType, Version norma else { ILCompilerPacks = new[] { newItem }; + // ILCompiler supports cross target compilation. If there is a cross-target request, we need to download that package as well + var targetsRuntimeIdentifier = NuGetUtils.GetBestMatchingRid(runtimeGraph, RuntimeIdentifier, packSupportedRuntimeIdentifiers, out bool wasInGraph2); + if (!hostRuntimeIdentifier.Equals(targetsRuntimeIdentifier)) + { + var runtimeIlcPackName = packPattern.Replace("**RID**", targetsRuntimeIdentifier); + TaskItem runtime2PackToDownload = new TaskItem(runtimeIlcPackName); + runtime2PackToDownload.SetMetadata(MetadataKeys.Version, packVersion); + packagesToDownload.Add(runtime2PackToDownload); + + var newItem2 = new TaskItem(runtimeIlcPackName); + newItem2.SetMetadata(MetadataKeys.NuGetPackageId, runtimeIlcPackName); + newItem2.SetMetadata(MetadataKeys.NuGetPackageVersion, packVersion); + ILCompilerPacks2 = 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..de55b6152ff6 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 @@ -121,6 +121,7 @@ Copyright (c) .NET Foundation. All rights reserved. + @@ -257,7 +258,14 @@ 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..4d50f6a946bd 100644 --- a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs +++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs @@ -78,6 +78,41 @@ 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) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + 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 sharedLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll" : ".so"; + var publishedDll = Path.Combine(publishDirectory, $"{projectName}{sharedLibSuffix}"); + 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) @@ -274,6 +309,103 @@ 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"; + testProject.AdditionalProperties["ObjCopyName"] = "objcopy"; + } + 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) From a182e3b3ee4f905e659d57e63289942a88569256 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Mon, 15 Aug 2022 06:17:43 -0700 Subject: [PATCH 2/5] FB --- .../ProcessFrameworkReferences.cs | 38 +++++++++++-------- ...T.Sdk.FrameworkReferenceResolution.targets | 10 ++--- .../GivenThatWeWantToPublishAnAotApp.cs | 2 - 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index b1e832d7beda..496e8b1ab563 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs @@ -99,10 +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[] ILCompilerPacks2 { get; set; } + public ITaskItem[] TargetILCompilerPacks { get; set; } // Runtime packs which aren't available for the specified RuntimeIdentifier [Output] @@ -620,20 +620,28 @@ 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 - var targetsRuntimeIdentifier = NuGetUtils.GetBestMatchingRid(runtimeGraph, RuntimeIdentifier, packSupportedRuntimeIdentifiers, out bool wasInGraph2); - if (!hostRuntimeIdentifier.Equals(targetsRuntimeIdentifier)) - { - var runtimeIlcPackName = packPattern.Replace("**RID**", targetsRuntimeIdentifier); - TaskItem runtime2PackToDownload = new TaskItem(runtimeIlcPackName); - runtime2PackToDownload.SetMetadata(MetadataKeys.Version, packVersion); - packagesToDownload.Add(runtime2PackToDownload); - - var newItem2 = new TaskItem(runtimeIlcPackName); - newItem2.SetMetadata(MetadataKeys.NuGetPackageId, runtimeIlcPackName); - newItem2.SetMetadata(MetadataKeys.NuGetPackageVersion, packVersion); - ILCompilerPacks2 = new[] { newItem2 }; + // We expect RuntimeIdentifier to be defined during publish but can allow during build + if (RuntimeIdentifier != null) + { + var targetsRuntimeIdentifier = NuGetUtils.GetBestMatchingRid(runtimeGraph, RuntimeIdentifier, packSupportedRuntimeIdentifiers, out bool wasInGraph2); + if (targetsRuntimeIdentifier == null) + { + return false; + } + if (!hostRuntimeIdentifier.Equals(targetsRuntimeIdentifier)) + { + var runtimeIlcPackName = packPattern.Replace("**RID**", targetsRuntimeIdentifier); + TaskItem runtime2PackToDownload = new TaskItem(runtimeIlcPackName); + runtime2PackToDownload.SetMetadata(MetadataKeys.Version, packVersion); + packagesToDownload.Add(runtime2PackToDownload); + + var newItem2 = new TaskItem(runtimeIlcPackName); + newItem2.SetMetadata(MetadataKeys.NuGetPackageId, runtimeIlcPackName); + newItem2.SetMetadata(MetadataKeys.NuGetPackageVersion, packVersion); + TargetILCompilerPacks = new[] { newItem2 }; + } } } 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 de55b6152ff6..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,8 +120,8 @@ Copyright (c) .NET Foundation. All rights reserved. - - + + @@ -253,17 +253,17 @@ Copyright (c) .NET Foundation. All rights reserved. - + Date: Mon, 15 Aug 2022 10:45:52 -0700 Subject: [PATCH 3/5] Restricting a low pri scenario validatin to windows ownly --- .../GivenThatWeWantToPublishAnAotApp.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs index 07ed3443f330..c20ecbf015e8 100644 --- a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs +++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAnAotApp.cs @@ -82,7 +82,7 @@ public void NativeAot_hw_runs_with_no_warnings_when_PublishAot_is_enabled(string [InlineData(ToolsetInfo.CurrentTargetFramework)] public void NativeAot_hw_runs_with_no_warnings_when_PublishAot_is_false(string targetFramework) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var projectName = "HellowWorldNativeAotApp"; var rid = EnvironmentInfo.GetCompatibleRid(targetFramework); @@ -100,8 +100,7 @@ public void NativeAot_hw_runs_with_no_warnings_when_PublishAot_is_false(string t .And.NotHaveStdErrContaining("warning"); 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 publishedDll = Path.Combine(publishDirectory, $"{projectName}.dll"); var publishedExe = Path.Combine(publishDirectory, $"{testProject.Name}{Constants.ExeSuffix}"); // PublishAot=false will be a normal publish From 6acfc2676f844546c928183d3266341898cf656b Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Mon, 15 Aug 2022 10:47:01 -0700 Subject: [PATCH 4/5] Update src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs Co-authored-by: Sven Boemer --- .../Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index 496e8b1ab563..e6985973c097 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs @@ -630,7 +630,7 @@ private bool AddAotOrR2RRuntimePackage(AotPackageType packageType, Version norma { return false; } - if (!hostRuntimeIdentifier.Equals(targetsRuntimeIdentifier)) + if (!hostRuntimeIdentifier.Equals(targetRuntimeIdentifier)) { var runtimeIlcPackName = packPattern.Replace("**RID**", targetsRuntimeIdentifier); TaskItem runtime2PackToDownload = new TaskItem(runtimeIlcPackName); From 373013deddcac8da795b949ca3a1ac4e165dcafa Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Mon, 15 Aug 2022 11:10:50 -0700 Subject: [PATCH 5/5] naming fb --- .../ProcessFrameworkReferences.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index e6985973c097..9447c16cbd02 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs @@ -625,17 +625,17 @@ private bool AddAotOrR2RRuntimePackage(AotPackageType packageType, Version norma // We expect RuntimeIdentifier to be defined during publish but can allow during build if (RuntimeIdentifier != null) { - var targetsRuntimeIdentifier = NuGetUtils.GetBestMatchingRid(runtimeGraph, RuntimeIdentifier, packSupportedRuntimeIdentifiers, out bool wasInGraph2); - if (targetsRuntimeIdentifier == 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**", targetsRuntimeIdentifier); - TaskItem runtime2PackToDownload = new TaskItem(runtimeIlcPackName); - runtime2PackToDownload.SetMetadata(MetadataKeys.Version, packVersion); - packagesToDownload.Add(runtime2PackToDownload); + 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);