-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add LoadPrunePackageDataFromNearestFramework parameter for building against newer TFMs #51978
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 6 commits
3bd93c7
2976066
d389078
272d2e9
6e76b8f
b8a4c52
bdf2384
67581b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,12 @@ namespace Microsoft.NET.Build.Tasks | |
| { | ||
| public class GetPackagesToPrune : TaskBase | ||
| { | ||
| // Minimum .NET Core version that supports package pruning | ||
| private const int MinSupportedFrameworkMajorVersion = 3; | ||
|
|
||
| // Minimum .NET Core version that uses prune package data instead of framework package data | ||
| private const int PrunePackageDataMinMajorVersion = 10; | ||
|
|
||
| [Required] | ||
| public string TargetFrameworkIdentifier { get; set; } | ||
|
|
||
|
|
@@ -35,6 +41,8 @@ public class GetPackagesToPrune : TaskBase | |
| [Required] | ||
| public bool AllowMissingPrunePackageData { get; set; } | ||
|
|
||
| public bool LoadPrunePackageDataFromNearestFramework { get; set; } | ||
|
||
|
|
||
| [Output] | ||
| public ITaskItem[] PackagesToPrune { get; set; } | ||
|
|
||
|
|
@@ -43,11 +51,13 @@ class CacheKey | |
| public string TargetFrameworkIdentifier { get; set; } | ||
| public string TargetFrameworkVersion { get; set; } | ||
| public HashSet<string> FrameworkReferences { get; set; } | ||
| public bool LoadPrunePackageDataFromNearestFramework { get; set; } | ||
|
|
||
| public override bool Equals(object obj) => obj is CacheKey key && | ||
| TargetFrameworkIdentifier == key.TargetFrameworkIdentifier && | ||
| TargetFrameworkVersion == key.TargetFrameworkVersion && | ||
| FrameworkReferences.SetEquals(key.FrameworkReferences); | ||
| FrameworkReferences.SetEquals(key.FrameworkReferences) && | ||
| LoadPrunePackageDataFromNearestFramework == key.LoadPrunePackageDataFromNearestFramework; | ||
| public override int GetHashCode() | ||
| { | ||
| #if NET | ||
|
|
@@ -58,6 +68,7 @@ public override int GetHashCode() | |
| { | ||
| hashCode.Add(frameworkReference); | ||
| } | ||
| hashCode.Add(LoadPrunePackageDataFromNearestFramework); | ||
| return hashCode.ToHashCode(); | ||
| #else | ||
| int hashCode = 1436330440; | ||
|
|
@@ -68,6 +79,7 @@ public override int GetHashCode() | |
| { | ||
| hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(frameworkReference); | ||
| } | ||
| hashCode = hashCode * -1521134295 + LoadPrunePackageDataFromNearestFramework.GetHashCode(); | ||
| return hashCode; | ||
| #endif | ||
| } | ||
|
|
@@ -102,7 +114,8 @@ protected override void ExecuteCore() | |
| { | ||
| TargetFrameworkIdentifier = TargetFrameworkIdentifier, | ||
| TargetFrameworkVersion = TargetFrameworkVersion, | ||
| FrameworkReferences = runtimeFrameworks.ToHashSet() | ||
| FrameworkReferences = runtimeFrameworks.ToHashSet(), | ||
| LoadPrunePackageDataFromNearestFramework = LoadPrunePackageDataFromNearestFramework | ||
| }; | ||
|
|
||
| // Cache framework package values per build | ||
|
|
@@ -124,16 +137,12 @@ static TaskItem[] LoadPackagesToPrune(CacheKey key, string[] targetingPackRoots, | |
|
|
||
| var targetFrameworkVersion = Version.Parse(key.TargetFrameworkVersion); | ||
|
|
||
| if (key.FrameworkReferences.Count == 0 && key.TargetFrameworkIdentifier.Equals(".NETCoreApp") && targetFrameworkVersion.Major >= 3) | ||
| if (key.FrameworkReferences.Count == 0 && key.TargetFrameworkIdentifier.Equals(".NETCoreApp") && targetFrameworkVersion.Major >= MinSupportedFrameworkMajorVersion) | ||
| { | ||
| // For .NET Core projects (3.0 and higher), don't prune any packages if there are no framework references | ||
| return Array.Empty<TaskItem>(); | ||
| } | ||
|
|
||
| // Use hard-coded / generated "framework package data" for .NET 9 and lower, .NET Framework, and .NET Standard | ||
| // Use bundled "prune package data" for .NET 10 and higher. During the redist build, this comes from targeting packs and is laid out in the PrunePackageData folder. | ||
| bool useFrameworkPackageData = !key.TargetFrameworkIdentifier.Equals(".NETCoreApp") || targetFrameworkVersion.Major < 10; | ||
|
|
||
| // Call DefaultIfEmpty() so that target frameworks without framework references will load data | ||
| foreach (var frameworkReference in key.FrameworkReferences.DefaultIfEmpty("")) | ||
| { | ||
|
|
@@ -147,41 +156,7 @@ static TaskItem[] LoadPackagesToPrune(CacheKey key, string[] targetingPackRoots, | |
| } | ||
| log.LogMessage(MessageImportance.Low, $"Loading packages to prune for {key.TargetFrameworkIdentifier} {key.TargetFrameworkVersion} {frameworkReference}"); | ||
|
|
||
| Dictionary<string, NuGetVersion> packagesForFrameworkReference; | ||
| if (useFrameworkPackageData) | ||
| { | ||
| packagesForFrameworkReference = LoadPackagesToPruneFromFrameworkPackages(key.TargetFrameworkIdentifier, key.TargetFrameworkVersion, frameworkReference); | ||
| if (packagesForFrameworkReference != null) | ||
| { | ||
| log.LogMessage("Loaded prune package data from framework packages"); | ||
| } | ||
| else | ||
| { | ||
| log.LogMessage("Failed to load prune package data from framework packages"); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| log.LogMessage("Loading prune package data from PrunePackageData folder"); | ||
| packagesForFrameworkReference = LoadPackagesToPruneFromPrunePackageData(key.TargetFrameworkIdentifier, key.TargetFrameworkVersion, frameworkReference, prunePackageDataRoot); | ||
|
|
||
| // For the version of the runtime that matches the current SDK version, we don't include the prune package data in the PrunePackageData folder. Rather, | ||
| // we can load it from the targeting packs that are packaged with the SDK. | ||
| if (packagesForFrameworkReference == null) | ||
| { | ||
| log.LogMessage("Failed to load prune package data from PrunePackageData folder, loading from targeting packs instead"); | ||
| packagesForFrameworkReference = LoadPackagesToPruneFromTargetingPack(log, key.TargetFrameworkIdentifier, key.TargetFrameworkVersion, frameworkReference, targetingPackRoots); | ||
| } | ||
|
|
||
| // Fall back to framework packages data for older framework for WindowsDesktop if necessary | ||
| // https://github.com/dotnet/windowsdesktop/issues/4904 | ||
| if (packagesForFrameworkReference == null && frameworkReference.Equals("Microsoft.WindowsDesktop.App", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| log.LogMessage("Failed to load prune package data for WindowsDesktop from targeting packs, loading from framework packages instead"); | ||
| packagesForFrameworkReference = LoadPackagesToPruneFromFrameworkPackages(key.TargetFrameworkIdentifier, key.TargetFrameworkVersion, frameworkReference, | ||
| acceptNearestMatch: true); | ||
| } | ||
| } | ||
| Dictionary<string, NuGetVersion> packagesForFrameworkReference = TryLoadPackagesToPruneForVersion(log, key.TargetFrameworkIdentifier, key.TargetFrameworkVersion, frameworkReference, targetingPackRoots, prunePackageDataRoot, key.LoadPrunePackageDataFromNearestFramework); | ||
|
|
||
| if (packagesForFrameworkReference == null) | ||
| { | ||
|
|
@@ -276,6 +251,66 @@ static Dictionary<string, NuGetVersion> LoadPackagesToPruneFromTargetingPack(Log | |
| return null; | ||
| } | ||
|
|
||
| static Dictionary<string, NuGetVersion> TryLoadPackagesToPruneForVersion(Logger log, string targetFrameworkIdentifier, string targetFrameworkVersion, string frameworkReference, string[] targetingPackRoots, string prunePackageDataRoot, bool loadPrunePackageDataFromNearestFramework) | ||
| { | ||
| var targetVersion = Version.Parse(targetFrameworkVersion); | ||
|
|
||
| // Use hard-coded / generated "framework package data" for .NET 9 and lower, .NET Framework, and .NET Standard | ||
| // Use bundled "prune package data" for .NET 10 and higher. During the redist build, this comes from targeting packs and is laid out in the PrunePackageData folder. | ||
| bool useFrameworkPackageData = !targetFrameworkIdentifier.Equals(".NETCoreApp") || targetVersion.Major < PrunePackageDataMinMajorVersion; | ||
|
|
||
| Dictionary<string, NuGetVersion> packages = null; | ||
|
|
||
| if (useFrameworkPackageData) | ||
| { | ||
| packages = LoadPackagesToPruneFromFrameworkPackages(targetFrameworkIdentifier, targetFrameworkVersion, frameworkReference); | ||
| if (packages != null) | ||
| { | ||
| log.LogMessage("Loaded prune package data from framework packages"); | ||
| } | ||
| else | ||
| { | ||
| log.LogMessage("Failed to load prune package data from framework packages"); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| log.LogMessage("Loading prune package data from PrunePackageData folder"); | ||
| packages = LoadPackagesToPruneFromPrunePackageData(targetFrameworkIdentifier, targetFrameworkVersion, frameworkReference, prunePackageDataRoot); | ||
|
|
||
| // For the version of the runtime that matches the current SDK version, we don't include the prune package data in the PrunePackageData folder. Rather, | ||
| // we can load it from the targeting packs that are packaged with the SDK. | ||
| if (packages == null) | ||
| { | ||
| log.LogMessage("Failed to load prune package data from PrunePackageData folder, loading from targeting packs instead"); | ||
| packages = LoadPackagesToPruneFromTargetingPack(log, targetFrameworkIdentifier, targetFrameworkVersion, frameworkReference, targetingPackRoots); | ||
| } | ||
|
|
||
| // Fall back to framework packages data for older framework for WindowsDesktop if necessary | ||
| // https://github.com/dotnet/windowsdesktop/issues/4904 | ||
| if (packages == null && frameworkReference.Equals("Microsoft.WindowsDesktop.App", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| log.LogMessage("Failed to load prune package data for WindowsDesktop from targeting packs, loading from framework packages instead"); | ||
| packages = LoadPackagesToPruneFromFrameworkPackages(targetFrameworkIdentifier, targetFrameworkVersion, frameworkReference, | ||
| acceptNearestMatch: true); | ||
| } | ||
| } | ||
|
|
||
| // If LoadPrunePackageDataFromNearestFramework is true and we still haven't found data, try the previous framework version | ||
| if (packages == null && loadPrunePackageDataFromNearestFramework) | ||
| { | ||
| // If we can go to a lower version, recursively try it | ||
| if (targetVersion.Major > MinSupportedFrameworkMajorVersion) | ||
| { | ||
| string fallbackVersion = $"{targetVersion.Major - 1}.0"; | ||
|
||
| log.LogMessage($"LoadPrunePackageDataFromNearestFramework is enabled, trying to load from framework version {fallbackVersion}"); | ||
| packages = TryLoadPackagesToPruneForVersion(log, targetFrameworkIdentifier, fallbackVersion, frameworkReference, targetingPackRoots, prunePackageDataRoot, loadPrunePackageDataFromNearestFramework); | ||
|
||
| } | ||
| } | ||
|
|
||
| return packages; | ||
| } | ||
|
|
||
| static void AddPackagesToPrune(Dictionary<string, NuGetVersion> packagesToPrune, IEnumerable<(string id, NuGetVersion version)> packagesToAdd, Logger log) | ||
| { | ||
| foreach (var package in packagesToAdd) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.