diff --git a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/ProcessFrameworkReferencesTests.cs b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/ProcessFrameworkReferencesTests.cs index 50b1b9c8df00..e4f298db6844 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/ProcessFrameworkReferencesTests.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks.UnitTests/ProcessFrameworkReferencesTests.cs @@ -76,6 +76,30 @@ public class ProcessFrameworkReferencesTests } """; + private const string NonPortableRid = "fedora.42-x64"; + + private static readonly string NonPortableRuntimeGraph = $$""" + { + "runtimes": { + "base": { + "#import": [] + }, + "any": { + "#import": ["base"] + }, + "linux": { + "#import": ["any"] + }, + "linux-x64": { + "#import": ["linux"] + }, + "{{NonPortableRid}}": { + "#import": ["linux-x64"] + } + } + } + """; + // Shared known framework references private readonly MockTaskItem _validWindowsSDKKnownFrameworkReference = CreateKnownFrameworkReference( "Microsoft.Windows.SDK.NET.Ref", "net5.0-windows10.0.18362", "10.0.18362.1-preview", @@ -491,6 +515,7 @@ public void It_handles_real_world_ridless_scenario_with_aot_and_trimming() ["TargetFramework"] = "net10.0", ["ILCompilerPackNamePattern"] = "runtime.**RID**.Microsoft.DotNet.ILCompiler", ["ILCompilerPackVersion"] = "10.0.0-rc.2.25457.102", + ["ILCompilerPortableRuntimeIdentifiers"] = "osx-x64;osx-arm64;win-x64;linux-x64", ["ILCompilerRuntimeIdentifiers"] = "osx-x64;osx-arm64;win-x64;linux-x64" }); @@ -766,5 +791,52 @@ public void It_handles_complex_cross_compilation_RuntimeIdentifiers() $"Should include runtime pack for supported RID: {rid}"); } } + + [Theory] + [InlineData(null, "linux-x64")] + [InlineData("linux-x64", "linux-x64")] + [InlineData(NonPortableRid, NonPortableRid)] + public void It_selects_correct_ILCompiler_based_on_RuntimeIdentifier(string? runtimeIdentifier, string expectedILCompilerRid) + { + var netCoreAppRef = CreateKnownFrameworkReference("Microsoft.NETCore.App", "net10.0", "10.0.1", + "Microsoft.NETCore.App.Runtime.**RID**", + "linux-x64;" + NonPortableRid); + + var ilCompilerPack = new MockTaskItem("Microsoft.DotNet.ILCompiler", new Dictionary + { + ["TargetFramework"] = "net10.0", + ["ILCompilerPackNamePattern"] = "runtime.**RID**.Microsoft.DotNet.ILCompiler", + ["ILCompilerPackVersion"] = "10.0.1", + ["ILCompilerPortableRuntimeIdentifiers"] = "linux-x64", + ["ILCompilerRuntimeIdentifiers"] = "linux-x64;" + NonPortableRid + }); + + var config = new TaskConfiguration + { + TargetFrameworkVersion = "10.0", + EnableRuntimePackDownload = true, + PublishAot = true, + NETCoreSdkRuntimeIdentifier = NonPortableRid, + NETCoreSdkPortableRuntimeIdentifier = "linux-x64", + RuntimeIdentifier = runtimeIdentifier, + RuntimeGraphPath = CreateRuntimeGraphFile(NonPortableRuntimeGraph), + FrameworkReferences = new[] { new MockTaskItem("Microsoft.NETCore.App", new Dictionary()) }, + KnownFrameworkReferences = new[] { netCoreAppRef }, + KnownILCompilerPacks = new[] { ilCompilerPack } + }; + + var task = CreateTask(config); + task.Execute().Should().BeTrue("Task should succeed"); + + // Validate that the expected ILCompiler pack is used + task.PackagesToDownload.Should().NotBeNull(); + task.PackagesToDownload.Should().Contain(p => p.ItemSpec.Contains("Microsoft.DotNet.ILCompiler"), + "Should include ILCompiler pack when PublishAot is true"); + + var ilCompilerPackage = task.PackagesToDownload.FirstOrDefault(p => p.ItemSpec.Contains("Microsoft.DotNet.ILCompiler")); + ilCompilerPackage.Should().NotBeNull(); + ilCompilerPackage!.ItemSpec.Should().Contain(expectedILCompilerRid, + $"Should use {expectedILCompilerRid} ILCompiler pack"); + } } } diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index 7b5b7bc0da15..fcc306fd454c 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs @@ -816,8 +816,10 @@ private ToolPackSupport AddToolPack( if (toolPackType is ToolPackType.Crossgen2 or ToolPackType.ILCompiler) { var packNamePattern = knownPack.GetMetadata(packName + "PackNamePattern"); - var packSupportedRuntimeIdentifiers = knownPack.GetMetadata(packName + "RuntimeIdentifiers").Split(';'); - var packSupportedPortableRuntimeIdentifiers = knownPack.GetMetadata(packName + "PortableRuntimeIdentifiers").Split(';'); + var packSupportedRuntimeIdentifiers = knownPack.GetMetadata(packName + "RuntimeIdentifiers").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + var packSupportedPortableRuntimeIdentifiers = knownPack.GetMetadata(packName + "PortableRuntimeIdentifiers").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + // Use the non-portable RIDs if there are no portable RIDs defined. + packSupportedPortableRuntimeIdentifiers = packSupportedPortableRuntimeIdentifiers.Length > 0 ? packSupportedPortableRuntimeIdentifiers : packSupportedRuntimeIdentifiers; // When publishing for a non-portable RID, prefer NETCoreSdkRuntimeIdentifier for the host. // Otherwise prefer the NETCoreSdkPortableRuntimeIdentifier. @@ -835,11 +837,11 @@ private ToolPackSupport AddToolPack( string? supportedPortableTargetRid = NuGetUtils.GetBestMatchingRid(runtimeGraph, runtimeIdentifier, packSupportedPortableRuntimeIdentifiers, out _); bool usePortable = !string.IsNullOrEmpty(NETCoreSdkPortableRuntimeIdentifier) - && supportedTargetRid is not null && supportedPortableTargetRid is not null && supportedTargetRid == supportedPortableTargetRid; // Get the best RID for the host machine, which will be used to validate that we can run crossgen for the target platform and architecture Log.LogMessage(MessageImportance.Low, $"Determining best RID for '{knownPack.ItemSpec}@{packVersion}' from among '{knownPack.GetMetadata(packName + "RuntimeIdentifiers")}'"); + string? hostRuntimeIdentifier = usePortable ? NuGetUtils.GetBestMatchingRid(runtimeGraph, NETCoreSdkPortableRuntimeIdentifier!, packSupportedPortableRuntimeIdentifiers, out _) : NuGetUtils.GetBestMatchingRid(runtimeGraph, NETCoreSdkRuntimeIdentifier!, packSupportedRuntimeIdentifiers, out _);