From 3acb9986d940ed0b3e3289af3e7edc615c78df7e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 1 Jul 2026 19:25:41 +0000
Subject: [PATCH 1/4] Initial plan
From 8eca0703200d2c2a28486a3d140a998a259cb6c4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 1 Jul 2026 19:39:22 +0000
Subject: [PATCH 2/4] Use any TFM for pointer tool settings
Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
---
.../targets/Microsoft.NET.PackTool.targets | 8 +++++++-
.../EndToEndToolTests.cs | 17 ++++++++++++++++-
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
index 79d08620cfc6..61eb947ab87c 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
@@ -205,9 +205,15 @@ NOTE: This file is imported from the following contexts, so be aware when writin
<_ToolRidPath Condition="'$(RuntimeIdentifier)' == ''">any
<_ToolRidPath Condition="'$(RuntimeIdentifier)' != ''">$(RuntimeIdentifier)
+ <_ToolSettingsTargetFrameworkPath>$(_ToolPackShortTargetFrameworkName)
+ <_ToolSettingsTargetFrameworkPath Condition="'$(_ToolPackageShouldIncludeImplementation)' != 'true' and '$(_UserSpecifiedToolPackageRids)' != ''">any
-
+
+ tools/$(_ToolSettingsTargetFrameworkPath)/$(_ToolRidPath)/
+
+
+
tools/$(_ToolPackShortTargetFrameworkName)/$(_ToolRidPath)/%(_GeneratedFiles.RecursiveDir)
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs b/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs
index 75786a86c338..353123037c14 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs
@@ -168,6 +168,7 @@ public void PackagesMultipleToolsWithASingleInvocation()
// top-level package should declare all of the rids
var topLevelPackage = packages.First(p => p.EndsWith($"{packageIdentifier}.{toolSettings.ToolPackageVersion}.nupkg"));
+ EnsureToolSettingsFileUsesAnyTfmAndRid(topLevelPackage);
var foundRids = GetRidsInSettingsFile(topLevelPackage);
foundRids.Should().BeEquivalentTo(expectedRids, "The top-level package should declare all of the RIDs for the tools it contains");
}
@@ -264,6 +265,7 @@ public void PackageToolWithAnyRid()
// top-level package should declare all of the rids
var topLevelPackage = packages.FirstOrDefault(p => p.EndsWith($"{packageIdentifier}.{toolSettings.ToolPackageVersion}.nupkg"));
topLevelPackage.Should().NotBeNull($"Package {packageIdentifier}.{toolSettings.ToolPackageVersion}.nupkg should be present in the tool packages directory")
+ .And.Satisfy(EnsureToolSettingsFileUsesAnyTfmAndRid)
.And.Satisfy(SupportAllOfTheseRuntimes([.. expectedRids, "any"]));
}
@@ -554,16 +556,29 @@ static string[] GetRidsInSettingsFile(XElement settingsXml)
return nodes;
}
+ static void EnsureToolSettingsFileUsesAnyTfmAndRid(string packagePath)
+ {
+ using var zipArchive = ZipFile.OpenRead(packagePath);
+ GetToolSettingsFileEntry(zipArchive).FullName.Should().Be("tools/any/any/DotnetToolSettings.xml");
+ }
+
static XElement GetToolSettingsFile(string packagePath)
{
using var zipArchive = ZipFile.OpenRead(packagePath);
- var nuspecEntry = zipArchive.Entries.First(e => e.Name == "DotnetToolSettings.xml")!;
+ var nuspecEntry = GetToolSettingsFileEntry(zipArchive);
var stream = nuspecEntry.Open();
var xml = XDocument.Load(stream, LoadOptions.None);
return xml.Root!;
}
+ static ZipArchiveEntry GetToolSettingsFileEntry(ZipArchive zipArchive)
+ {
+ var settingsEntries = zipArchive.Entries.Where(e => e.Name == "DotnetToolSettings.xml").ToArray();
+ settingsEntries.Should().ContainSingle("tool packages should contain exactly one DotnetToolSettings.xml file");
+ return settingsEntries[0];
+ }
+
[TestMethod]
public void InstallToolWithHigherFrameworkAsGlobalToolShowsAppropriateError()
{
From e4842008726011ac1198f07cfe839348ea34eccc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 1 Jul 2026 19:39:56 +0000
Subject: [PATCH 3/4] Address review feedback on tool packaging fix
Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
---
.../targets/Microsoft.NET.PackTool.targets | 1 +
.../EndToEndToolTests.cs | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
index 61eb947ab87c..b483c7625ce5 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
@@ -206,6 +206,7 @@ NOTE: This file is imported from the following contexts, so be aware when writin
<_ToolRidPath Condition="'$(RuntimeIdentifier)' == ''">any
<_ToolRidPath Condition="'$(RuntimeIdentifier)' != ''">$(RuntimeIdentifier)
<_ToolSettingsTargetFrameworkPath>$(_ToolPackShortTargetFrameworkName)
+
<_ToolSettingsTargetFrameworkPath Condition="'$(_ToolPackageShouldIncludeImplementation)' != 'true' and '$(_UserSpecifiedToolPackageRids)' != ''">any
diff --git a/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs b/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs
index 353123037c14..6ce8f672984f 100644
--- a/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs
+++ b/test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs
@@ -565,8 +565,8 @@ static void EnsureToolSettingsFileUsesAnyTfmAndRid(string packagePath)
static XElement GetToolSettingsFile(string packagePath)
{
using var zipArchive = ZipFile.OpenRead(packagePath);
- var nuspecEntry = GetToolSettingsFileEntry(zipArchive);
- var stream = nuspecEntry.Open();
+ var toolSettingsEntry = GetToolSettingsFileEntry(zipArchive);
+ var stream = toolSettingsEntry.Open();
var xml = XDocument.Load(stream, LoadOptions.None);
return xml.Root!;
From be84adc9f99610f69455049183732f911be2cc79 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 1 Jul 2026 19:58:49 +0000
Subject: [PATCH 4/4] Simplify pack tool settings handling
Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
---
.../targets/Microsoft.NET.PackTool.targets | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
index b483c7625ce5..8f6f6f14e137 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.PackTool.targets
@@ -186,7 +186,6 @@ NOTE: This file is imported from the following contexts, so be aware when writin
Condition=" '$(PackAsTool)' == 'true' "
Returns="@(TfmSpecificPackageFile)">
- <_GeneratedFiles Include="$(_ToolsSettingsFilePath)"/>