From 122f6fd1f5edbb64ffaad021540f7acf908ddbe1 Mon Sep 17 00:00:00 2001 From: Sarah Oslund Date: Thu, 25 Jun 2020 11:37:08 -0700 Subject: [PATCH] Work around for runtime pack profiles with differing runtime IDs --- .../ProcessFrameworkReferences.cs | 103 ++++++++++-------- .../KnownRuntimePackTests.cs | 42 ++++++- 2 files changed, 94 insertions(+), 51 deletions(-) diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs index f7aaacb7cb46..19c9670a2192 100644 --- a/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs +++ b/src/Tasks/Microsoft.NET.Build.Tasks/ProcessFrameworkReferences.cs @@ -6,7 +6,6 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; -using System.Text.RegularExpressions; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Newtonsoft.Json; @@ -230,58 +229,74 @@ protected override void ExecuteCore() isTrimmable = selectedRuntimePack?.IsTrimmable; } - // Only add runtime packs where the framework reference name matches the RuntimeFrameworkName - // Framework references for "profiles" will use the runtime pack from the corresponding non-profile framework + bool includeInPackageDownload; + KnownRuntimePack runtimePackForRuntimeIDProcessing; if (knownFrameworkReference.Name.Equals(knownFrameworkReference.RuntimeFrameworkName, StringComparison.OrdinalIgnoreCase)) { - bool processedPrimaryRuntimeIdentifier = false; + // Only add runtime packs where the framework reference name matches the RuntimeFrameworkName + // Framework references for "profiles" will use the runtime pack from the corresponding non-profile framework + runtimePackForRuntimeIDProcessing = selectedRuntimePack.Value; + includeInPackageDownload = true; + } + else if (!knownFrameworkReference.RuntimePackRuntimeIdentifiers.Equals(selectedRuntimePack?.RuntimePackRuntimeIdentifiers)) + { + // If the profile has a different set of runtime identifiers than the runtime pack, use the profile. + runtimePackForRuntimeIDProcessing = knownFrameworkReference.ToKnownRuntimePack(); + includeInPackageDownload = true; + } + else + { + // For the remaining profiles, don't include them in package download but add them to unavaliable if necessary. + runtimePackForRuntimeIDProcessing = knownFrameworkReference.ToKnownRuntimePack(); + includeInPackageDownload = false; + } - if ((SelfContained || ReadyToRunEnabled) && - !string.IsNullOrEmpty(RuntimeIdentifier) && - selectedRuntimePack != null && - !string.IsNullOrEmpty(selectedRuntimePack?.RuntimePackNamePatterns)) - { + bool processedPrimaryRuntimeIdentifier = false; - // Find other KnownFrameworkReferences that map to the same runtime pack, if any - List additionalFrameworkReferencesForRuntimePack = null; - foreach (var additionalKnownFrameworkReference in knownFrameworkReferencesForTargetFramework) + if ((SelfContained || ReadyToRunEnabled) && + !string.IsNullOrEmpty(RuntimeIdentifier) && + selectedRuntimePack != null && + !string.IsNullOrEmpty(selectedRuntimePack?.RuntimePackNamePatterns)) + { + + // Find other KnownFrameworkReferences that map to the same runtime pack, if any + List additionalFrameworkReferencesForRuntimePack = null; + foreach (var additionalKnownFrameworkReference in knownFrameworkReferencesForTargetFramework) + { + if (additionalKnownFrameworkReference.RuntimeFrameworkName.Equals(knownFrameworkReference.RuntimeFrameworkName, StringComparison.OrdinalIgnoreCase) && + !additionalKnownFrameworkReference.RuntimeFrameworkName.Equals(additionalKnownFrameworkReference.Name, StringComparison.OrdinalIgnoreCase)) { - if (additionalKnownFrameworkReference.RuntimeFrameworkName.Equals(knownFrameworkReference.RuntimeFrameworkName, StringComparison.OrdinalIgnoreCase) && - !additionalKnownFrameworkReference.RuntimeFrameworkName.Equals(additionalKnownFrameworkReference.Name, StringComparison.OrdinalIgnoreCase)) + if (additionalFrameworkReferencesForRuntimePack == null) { - if (additionalFrameworkReferencesForRuntimePack == null) - { - additionalFrameworkReferencesForRuntimePack = new List(); - } - additionalFrameworkReferencesForRuntimePack.Add(additionalKnownFrameworkReference.Name); + additionalFrameworkReferencesForRuntimePack = new List(); } + additionalFrameworkReferencesForRuntimePack.Add(additionalKnownFrameworkReference.Name); } + } - ProcessRuntimeIdentifier(RuntimeIdentifier, selectedRuntimePack.Value, runtimePackVersion, additionalFrameworkReferencesForRuntimePack, - unrecognizedRuntimeIdentifiers, unavailableRuntimePacks, runtimePacks, packagesToDownload, isTrimmable); + ProcessRuntimeIdentifier(RuntimeIdentifier, runtimePackForRuntimeIDProcessing, runtimePackVersion, additionalFrameworkReferencesForRuntimePack, + unrecognizedRuntimeIdentifiers, unavailableRuntimePacks, runtimePacks, packagesToDownload, isTrimmable, includeInPackageDownload); - processedPrimaryRuntimeIdentifier = true; - } + processedPrimaryRuntimeIdentifier = true; + } - if (RuntimeIdentifiers != null) + if (RuntimeIdentifiers != null) + { + foreach (var runtimeIdentifier in RuntimeIdentifiers) { - foreach (var runtimeIdentifier in RuntimeIdentifiers) + if (processedPrimaryRuntimeIdentifier && runtimeIdentifier == this.RuntimeIdentifier) { - if (processedPrimaryRuntimeIdentifier && runtimeIdentifier == this.RuntimeIdentifier) - { - // We've already processed this RID - continue; - } - - // Pass in null for the runtimePacks list, as for these runtime identifiers we only want to - // download the runtime packs, but not use the assets from them - ProcessRuntimeIdentifier(runtimeIdentifier, selectedRuntimePack.Value, runtimePackVersion, additionalFrameworkReferencesForRuntimePack: null, - unrecognizedRuntimeIdentifiers, unavailableRuntimePacks, runtimePacks: null, packagesToDownload, isTrimmable); + // We've already processed this RID + continue; } + + // Pass in null for the runtimePacks list, as for these runtime identifiers we only want to + // download the runtime packs, but not use the assets from them + ProcessRuntimeIdentifier(runtimeIdentifier, runtimePackForRuntimeIDProcessing, runtimePackVersion, additionalFrameworkReferencesForRuntimePack: null, + unrecognizedRuntimeIdentifiers, unavailableRuntimePacks, runtimePacks: null, packagesToDownload, isTrimmable, includeInPackageDownload); } } - if (!string.IsNullOrEmpty(knownFrameworkReference.RuntimeFrameworkName)) { TaskItem runtimeFramework = new TaskItem(knownFrameworkReference.RuntimeFrameworkName); @@ -370,7 +385,7 @@ protected override void ExecuteCore() { string runtimePackDescriptionForErrorMessage = knownFrameworkReference.RuntimeFrameworkName + (requiredLabelsMetadata == string.Empty ? string.Empty : ":" + requiredLabelsMetadata); - + Log.LogError(Strings.ConflictingRuntimePackInformation, runtimePackDescriptionForErrorMessage, string.Join(Environment.NewLine, matchingRuntimePacks.Select(rp => rp.RuntimePackNamePatterns))); @@ -387,7 +402,8 @@ private void ProcessRuntimeIdentifier( List unavailableRuntimePacks, List runtimePacks, List packagesToDownload, - string isTrimmable) + string isTrimmable, + bool addToPackageDownload) { var runtimeGraph = new RuntimeGraphCache(this).GetRuntimeGraph(RuntimeGraphPath); var knownFrameworkReferenceRuntimePackRuntimeIdentifiers = selectedRuntimePack.RuntimePackRuntimeIdentifiers.Split(';'); @@ -418,7 +434,7 @@ private void ProcessRuntimeIdentifier( unrecognizedRuntimeIdentifiers.Add(runtimeIdentifier); } } - else + else if (addToPackageDownload) { foreach (var runtimePackNamePattern in selectedRuntimePack.RuntimePackNamePatterns.Split(';')) { @@ -620,18 +636,13 @@ public KnownFrameworkReference(ITaskItem item) // The framework name to write to the runtimeconfig file (and the name of the folder under dotnet/shared) public string RuntimeFrameworkName => _item.GetMetadata(MetadataKeys.RuntimeFrameworkName); public string DefaultRuntimeFrameworkVersion => _item.GetMetadata("DefaultRuntimeFrameworkVersion"); - //public string LatestRuntimeFrameworkVersion => _item.GetMetadata("LatestRuntimeFrameworkVersion"); // The ID of the targeting pack NuGet package to reference public string TargetingPackName => _item.GetMetadata("TargetingPackName"); public string TargetingPackVersion => _item.GetMetadata("TargetingPackVersion"); public string TargetingPackFormat => _item.GetMetadata("TargetingPackFormat"); - //public string RuntimePackNamePatterns => _item.GetMetadata("RuntimePackNamePatterns"); - - //public string RuntimePackRuntimeIdentifiers => _item.GetMetadata(MetadataKeys.RuntimePackRuntimeIdentifiers); - - //public string IsTrimmable => _item.GetMetadata(MetadataKeys.IsTrimmable); + public string RuntimePackRuntimeIdentifiers => _item.GetMetadata(MetadataKeys.RuntimePackRuntimeIdentifiers); public bool IsWindowsOnly => _item.HasMetadataValue("IsWindowsOnly", "true"); @@ -668,8 +679,6 @@ public KnownRuntimePack(ITaskItem item) public string Name => _item.ItemSpec; //// The framework name to write to the runtimeconfig file (and the name of the folder under dotnet/shared) - //public string RuntimeFrameworkName => _item.GetMetadata(MetadataKeys.RuntimeFrameworkName); - //public string DefaultRuntimeFrameworkVersion => _item.GetMetadata("DefaultRuntimeFrameworkVersion"); public string LatestRuntimeFrameworkVersion => _item.GetMetadata("LatestRuntimeFrameworkVersion"); public string RuntimePackNamePatterns => _item.GetMetadata("RuntimePackNamePatterns"); diff --git a/src/Tests/Microsoft.NET.Build.Tests/KnownRuntimePackTests.cs b/src/Tests/Microsoft.NET.Build.Tests/KnownRuntimePackTests.cs index 1ecf5ebd1fe9..5274a61a38da 100644 --- a/src/Tests/Microsoft.NET.Build.Tests/KnownRuntimePackTests.cs +++ b/src/Tests/Microsoft.NET.Build.Tests/KnownRuntimePackTests.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; +using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Xml.Linq; using FluentAssertions; using Microsoft.NET.TestFramework; @@ -139,5 +136,42 @@ private void AddItem(TestAsset testAsset, XElement item) itemGroup.Add(item); }); } + + [WindowsOnlyFact] + public void ItCanPublishArm64Winforms() + { + var testDirectory = _testAssetsManager.CreateTestDirectory().Path; + + var newCommand = new DotnetCommand(Log, "new", "winforms", "--no-restore"); + newCommand.WorkingDirectory = testDirectory; + newCommand.Execute().Should().Pass(); + + new PublishCommand(Log, testDirectory) + .Execute("/p:RuntimeIdentifier=win-arm64") + .Should() + .Pass(); + + var selfContainedPublishDir = new DirectoryInfo(testDirectory) + .Sub("bin").Sub("Debug").GetDirectories().FirstOrDefault() + .Sub("win-arm64").Sub("publish"); + + selfContainedPublishDir.Should().HaveFilesMatching("System.Windows.Forms.dll", SearchOption.TopDirectoryOnly); + selfContainedPublishDir.Should().HaveFilesMatching($"{new DirectoryInfo(testDirectory).Name}.dll", SearchOption.TopDirectoryOnly); + } + + [WindowsOnlyFact] + public void ItCantPublishArm64Wpf() + { + var testDirectory = _testAssetsManager.CreateTestDirectory().Path; + + var newCommand = new DotnetCommand(Log, "new", "wpf", "--no-restore"); + newCommand.WorkingDirectory = testDirectory; + newCommand.Execute().Should().Pass(); + + new PublishCommand(Log, testDirectory) + .Execute("/p:RuntimeIdentifier=win-arm64") + .Should() + .Fail(); + } } }