Skip to content
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

Improve pruned package data loading and handling #46898

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
621b0e1
Include package prune data in SDK layout
dsplaisted Jan 31, 2025
e28a32a
Refactor package prune data cache code
dsplaisted Jan 31, 2025
cc00bc5
Generate Package Prune Data in stage 2 redist
dsplaisted Feb 2, 2025
4a74dd0
Rename task
dsplaisted Feb 2, 2025
3a8dcf6
Compare prune package data from framework packages and PrunePackageData
dsplaisted Feb 10, 2025
e468db1
Change source for prune package data depending on target framework
dsplaisted Feb 14, 2025
c59c18d
Remove code to compare Prune Package Data and framework packages data
dsplaisted Feb 14, 2025
a84537a
Add prune package tests for different target frameworks, and fix load…
dsplaisted Feb 17, 2025
64cdcba
Map framework reference profiles when getting pruned packages
dsplaisted Feb 18, 2025
7092eff
Remove comment
dsplaisted Feb 18, 2025
63af8e4
Prune any patches of pruned packages
dsplaisted Feb 18, 2025
cdfd3f1
Test fixes
dsplaisted Feb 26, 2025
e4f3244
Bring back CollatePackageDownloads task for package pruning
dsplaisted Feb 28, 2025
9dfd18f
Apply suggestions from code review
dsplaisted Mar 4, 2025
75252a6
Code review feedback and comment cleanup
dsplaisted Mar 4, 2025
fbce075
Fix copy/paste issue in GenerateBundledVersions.targets
dsplaisted Mar 4, 2025
65f9792
Support overriding or providing additional paths for prune package data
dsplaisted Mar 4, 2025
847eb43
Don't try to get package prune data for frameworks that don't have it.
dsplaisted Mar 5, 2025
324a690
Fix empty framework reference in prune package data
dsplaisted Mar 5, 2025
4432196
Add logging for GetPackagesToPrune
dsplaisted Mar 6, 2025
ac0bf12
Add error message if prune package data can't be found, and add prope…
dsplaisted Mar 6, 2025
0d94ae8
Add localization comment
dsplaisted Mar 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
<Output TaskParameter="DependencyVersion" PropertyName="DepAspNetCoreVersion" />
<Output TaskParameter="DependencyCommit" PropertyName="DepAspNetCoreCommit" />
</GetDependencyInfo>

<GetDependencyInfo
VersionDetailsXmlFile="$(RepoRoot)eng/Version.Details.xml"
DependencyName="Microsoft.WindowsDesktop.App.Ref">
Expand Down Expand Up @@ -535,6 +534,7 @@ Copyright (c) .NET Foundation. All rights reserved.
<PropertyGroup>
<NetCoreRoot Condition="'%24(NetCoreRoot)' == ''">%24([MSBuild]::NormalizePath('%24(MSBuildThisFileDirectory)..\..\'))</NetCoreRoot>
<NetCoreTargetingPackRoot Condition="'%24(NetCoreTargetingPackRoot)' == ''">%24([MSBuild]::EnsureTrailingSlash('%24(NetCoreRoot)'))packs</NetCoreTargetingPackRoot>
<PrunePackageDataRoot Condition="'%24(PrunePackageDataRoot)' == ''">%24([MSBuild]::EnsureTrailingSlash('%24(MSBuildThisFileDirectory)'))PrunePackageData</PrunePackageDataRoot>

<_NetFrameworkHostedCompilersVersion>$(MicrosoftNetCompilersToolsetFrameworkPackageVersion)</_NetFrameworkHostedCompilersVersion>
<NETCoreAppMaximumVersion>$(_NETCoreAppTargetFrameworkVersion)</NETCoreAppMaximumVersion>
Expand Down
1 change: 1 addition & 0 deletions src/Layout/redist/redist.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<Import Project="targets\BundledTools.targets" />
<Import Project="targets\PublishDotnetWatch.targets" />
<Import Project="targets\GenerateLayout.targets" />
<Import Project="targets\GeneratePackagePruneData.targets" />
<Import Project="targets\OverlaySdkOnLKG.targets" Condition="'$(DotNetBuild)' != 'true'" />

<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions src/Layout/redist/targets/GenerateLayout.targets
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@
PublishFSharp;
PublishBlazorWasmTools;
PublishStaticWebAssetsTools;
GeneratePackagePruneData;
GenerateCliRuntimeConfigurationFiles;
MakeFscRunnableAndMoveToPublishDir;
RemoveFscFilesAfterPublish;
Expand Down
60 changes: 60 additions & 0 deletions src/Layout/redist/targets/GeneratePackagePruneData.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<Project>

<Target Name="GeneratePackagePruneData">

<GeneratePackagePruneDataDownloads
NETCoreAppTargetFrameworkVersion="$(MicrosoftNETCoreAppRuntimePackageVersion)">
<Output TaskParameter="TargetingPackDownloads" ItemName="TargetingPackForPruneData" />
</GeneratePackagePruneDataDownloads>

<CollatePackageDownloads Packages="@(TargetingPackForPruneData)">
<Output TaskParameter="PackageDownloads" ItemName="TargetingPackForPruneDataCollated" />
</CollatePackageDownloads>

<!-- Can't run custom tasks in the build before NuGet restore, so create a separate project and restore that to download the packages -->
Copy link
Member

@ViktorHofer ViktorHofer Mar 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This worries me. I submitted various PRs in the last month that removed these in-built restores. That has multiple downsides:

  • The build doesn't work without network connection after an initial build.cmd/sh -restore. "Air plane mode"
  • With a coming SFI requirement, the times when we can hit the network will be restricted.
  • Increased complexity and the build is slower because of the intermediate projects.

We hit that same limitation in SBRP (https://github.com/dotnet/source-build-reference-packages/blob/232bcf31aad21949f80d6706720540b85e43fff3/src/packageSourceGenerator/PackageSourceGenerator.proj#L98C9-L104) and decided to introduce an inline task that can run before restore.

Now that I see this additional use-case, I would prefer if we move the CollatePackageDownloads task into the Arcade SDK which makes it available before project restore and solves this recurring problem for our own repositories (SBRP, SDK and potentially others).

FWIW I'm not sure why NuGet requires customers to collate the items in the first place. Why can't NuGet parse such items:

<PackageDownload Include="x" Version="[7.0.0]" />
<PackageDownload Include="x" Version="[8.0.0]" />

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not just the collating, there's also the GeneratePackagePruneDataDownloads task.

It would be nice if we can find a good pattern for running custom tasks that help determine what needs to be restored.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Looking at the GeneratePackagePruneDataDownloads task, I don't think that needs to be a build task at all. It should be able to express what the task is doing in pure msbuild syntax with even less code with item batching.

<PropertyGroup>
<PrunePackDownloadProjectContent>
<![CDATA[
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(TargetFramework)</TargetFramework>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
</PropertyGroup>
<ItemGroup>
@(TargetingPackForPruneDataCollated->'<PackageDownload Include="%(Identity)" Version="%(Version)" />', '
')
</ItemGroup>
</Project>
]]>
</PrunePackDownloadProjectContent>
<!-- Escape semicolons as %3B in order to avoid being interpreted as line splits in WriteLinesToFile -->
<PrunePackDownloadProjectContent>$(PrunePackDownloadProjectContent.Replace(';', '%3B'))</PrunePackDownloadProjectContent>
<PrunePackDownloadProjectDirectory>$(IntermediateOutputPath)PrunePackDownloader\</PrunePackDownloadProjectDirectory>
<PrunePackDownloadProjectPath>$(PrunePackDownloadProjectDirectory)PrunePackPackageDownloader.csproj</PrunePackDownloadProjectPath>
</PropertyGroup>

<MakeDir Directories="$(PrunePackDownloadProjectDirectory)" />
<WriteLinesToFile Lines="$(PrunePackDownloadProjectContent)"
File="$(PrunePackDownloadProjectPath)"
Overwrite="True" WriteOnlyWhenDifferent="True" />

<MSBuild Projects="$(PrunePackDownloadProjectPath)"
Targets="Restore" />


<ItemGroup>
<PrunePackageCopyData Include="@(TargetingPackForPruneData)">
<Source>$(NuGetPackageRoot)$([MSBuild]::ValueOrDefault('%(Identity)', '').ToLower())/%(PackageVersion)/data/PackageOverrides.txt</Source>
<Destination>$(OutputPath)/PrunePackageData/%(TargetFrameworkVersion)/%(FrameworkName)/PackageOverrides.txt</Destination>
</PrunePackageCopyData>
</ItemGroup>

<Copy SourceFiles="%(PrunePackageCopyData.Source)"
DestinationFiles="%(Destination)"
SkipUnchangedFiles="true"
Condition="Exists(%(PrunePackageCopyData.Source))"
/>

</Target>

</Project>
35 changes: 21 additions & 14 deletions src/Tasks/Common/ConflictResolution/PackageOverride.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ internal class PackageOverride
public string PackageName { get; }
public Dictionary<string, OverrideVersion> OverriddenPackages { get; }

private PackageOverride(string packageName, IEnumerable<Tuple<string, OverrideVersion>> overriddenPackages)
private PackageOverride(string packageName, IEnumerable<(string id, OverrideVersion version)> overriddenPackages)
{
PackageName = packageName;

OverriddenPackages = new Dictionary<string, OverrideVersion>(StringComparer.OrdinalIgnoreCase);
foreach (Tuple<string, OverrideVersion> package in overriddenPackages)
foreach (var package in overriddenPackages)
{
OverriddenPackages[package.Item1] = package.Item2;
OverriddenPackages[package.id] = package.version;
}
}

Expand All @@ -44,27 +44,34 @@ public static PackageOverride Create(ITaskItem packageOverrideItem)
return new PackageOverride(packageName, CreateOverriddenPackages(overriddenPackagesString));
}

private static IEnumerable<Tuple<string, OverrideVersion>> CreateOverriddenPackages(string overriddenPackagesString)
private static IEnumerable<(string id, OverrideVersion version)> CreateOverriddenPackages(string overriddenPackagesString)
{
if (!string.IsNullOrEmpty(overriddenPackagesString))
{
overriddenPackagesString = overriddenPackagesString.Trim();
string[] overriddenPackagesAndVersions = overriddenPackagesString.Split(new char[] { ';', '\r', '\n', ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string overriddenPackagesAndVersion in overriddenPackagesAndVersions)
return CreateOverriddenPackages(overriddenPackagesAndVersions);
}
return Enumerable.Empty<(string id, OverrideVersion version)>();
}

public static IEnumerable<(string id, OverrideVersion version)> CreateOverriddenPackages(IEnumerable<string> packageOverrideFileLines)
{
foreach (string overriddenPackagesAndVersion in packageOverrideFileLines)
{
string trimmedOverriddenPackagesAndVersion = overriddenPackagesAndVersion.Trim();
int separatorIndex = trimmedOverriddenPackagesAndVersion.IndexOf('|');
if (separatorIndex != -1)
{
string trimmedOverriddenPackagesAndVersion = overriddenPackagesAndVersion.Trim();
int separatorIndex = trimmedOverriddenPackagesAndVersion.IndexOf('|');
if (separatorIndex != -1)
string versionString = trimmedOverriddenPackagesAndVersion.Substring(separatorIndex + 1);
string overriddenPackage = trimmedOverriddenPackagesAndVersion.Substring(0, separatorIndex);
if (OverrideVersion.TryParse(versionString, out OverrideVersion? version))
{
string versionString = trimmedOverriddenPackagesAndVersion.Substring(separatorIndex + 1);
string overriddenPackage = trimmedOverriddenPackagesAndVersion.Substring(0, separatorIndex);
if (OverrideVersion.TryParse(versionString, out OverrideVersion? version))
{
yield return Tuple.Create(overriddenPackage, version);
}
yield return (overriddenPackage, version);
}
}
}

}
}
}
6 changes: 5 additions & 1 deletion src/Tasks/Common/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -978,9 +978,13 @@ You may need to build the project on another operating system or architecture, o
<value>NETSDK1224: ASP.NET Core framework assets are not supported for the target framework.</value>
<comment>{StrBegins="NETSDK1224: "}</comment>
</data>
<!-- The latest message added is NativeCompilationRequiresPublishing. Please update this value with each PR to catch parallel PRs both adding a new message -->
<data name="NativeCompilationRequiresPublishing" xml:space="preserve">
<value>NETSDK1225: Native compilation is not supported when invoking the Publish target directly. Try running dotnet publish.</value>
<comment>{StrBegins="NETSDK1225: "}</comment>
</data>
<!-- The latest message added is PrunePackageDataNotFound. Please update this value with each PR to catch parallel PRs both adding a new message -->
<data name="PrunePackageDataNotFound" xml:space="preserve">
<value>NETSDK1226: Prune Package data not found {0} {1} {2}. To ignore this error, set the AllowMissingPrunePackageData to true.</value>
<comment>{StrBegins="NETSDK1226: "}</comment>
</data>
</root>
5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Common/Resources/xlf/Strings.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading