From 24af2ec5fad674613d02e85b7f5df5497eccc52b Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Sat, 19 Jul 2025 10:24:59 -0500 Subject: [PATCH 1/3] use TL summary all the time beacuse we have a big build --- build.cmd | 2 +- build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.cmd b/build.cmd index 9f103b9e1ab6..89f266240e84 100644 --- a/build.cmd +++ b/build.cmd @@ -8,5 +8,5 @@ if %errorlevel%==0 ( set skipFlags="/p:SkipUsingCrossgen=true /p:SkipBuildingInstallers=true" ) set DOTNET_SYSTEM_NET_SECURITY_NOREVOCATIONCHECKBYDEFAULT=true -powershell -NoLogo -NoProfile -ExecutionPolicy ByPass -command "& """%~dp0eng\common\build.ps1""" -restore -build -msbuildEngine dotnet %skipFlags% %*" +powershell -NoLogo -NoProfile -ExecutionPolicy ByPass -command "& """%~dp0eng\common\build.ps1""" -restore -build -msbuildEngine dotnet %skipFlags% /tlp:summary %*" exit /b %ErrorLevel% diff --git a/build.sh b/build.sh index 96189c91eadb..49b1e0e55773 100755 --- a/build.sh +++ b/build.sh @@ -14,4 +14,4 @@ if [[ "$@" != *"-pack"* ]]; then fi export DOTNET_SYSTEM_NET_SECURITY_NOREVOCATIONCHECKBYDEFAULT="true" -. "$ScriptRoot/eng/common/build.sh" --build --restore $skipFlags "$@" +. "$ScriptRoot/eng/common/build.sh" --build --restore $skipFlags /tlp:summary "$@" From b498344c97cc2574f148aa497474202cff263983 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Sat, 19 Jul 2025 10:25:39 -0500 Subject: [PATCH 2/3] bump MSBuild API versions and dependencies, hack through VS-env validations, report all VS-env validation errors in one batch --- eng/Versions.props | 15 ++++++----- ...Microsoft.DotNet.MSBuildSdkResolver.csproj | 27 ++++++++++--------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 49b3f3f26bf9..4f61e9413886 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -133,16 +133,16 @@ 10.0.0-preview.7.25367.101 - 8.0.0 + 9.0.0 2.0.0-preview.1.24427.4 4.5.1 - 8.0.0 + 9.0.0 4.5.5 - 8.0.0 - 8.0.0 - 8.0.5 + 9.0.0 + 9.0.0 + 9.0.0 4.5.4 - 8.0.0 + 9.0.0 @@ -190,7 +190,8 @@ Additionally, set the MinimumVSVersion for the installer UI that's required for targeting NetCurrent --> 17.15.0-preview-25367-101 17.15.0-preview-25367-101 - 17.11.4 + + $(MicrosoftBuildVersion) 17.13 diff --git a/src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.csproj b/src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.csproj index 58403f591e60..f214ae97c297 100644 --- a/src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.csproj +++ b/src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/Microsoft.DotNet.MSBuildSdkResolver.csproj @@ -105,18 +105,19 @@ - - - + - - - - - - + + + + + + + + + + - @@ -127,9 +128,11 @@ + Condition="!($([System.String]::Copy('$(ResolvedDependenciesList)').Contains('%(ExpectedDependencies.Identity)')))" + ContinueOnError="true" /> + Condition="!($([System.String]::Copy('$(ExpectedDependenciesList)').Contains('%(ResolvedDependencies.FusionName)')))" + ContinueOnError="true" /> From 3ab8cb9ab1db18c6c7325b7df2c2fb12b7107d78 Mon Sep 17 00:00:00 2001 From: Chet Husk Date: Sat, 19 Jul 2025 10:26:03 -0500 Subject: [PATCH 3/3] set env vars from resolver APIs --- .../MSBuildSdkResolver.cs | 41 +++++++++++-------- .../GivenAnMSBuildSdkResolver.cs | 33 ++++++++++----- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs b/src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs index 5bf7a44cb716..8a0c1f559650 100644 --- a/src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs +++ b/src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs @@ -32,9 +32,11 @@ public sealed class DotNetMSBuildSdkResolver : SdkResolver private readonly Func _getMsbuildRuntime; private readonly NETCoreSdkResolver _netCoreSdkResolver; + private const string DOTNET_HOST = nameof(DOTNET_HOST); private const string DotnetHostExperimentalKey = "DOTNET_EXPERIMENTAL_HOST_PATH"; private const string MSBuildTaskHostRuntimeVersion = "SdkResolverMSBuildTaskHostRuntimeVersion"; - + private const string SdkResolverHonoredGlobalJson = "SdkResolverHonoredGlobalJson"; + private const string SdkResolverGlobalJsonPath = "SdkResolverGlobalJsonPath"; private static CachingWorkloadResolver _staticWorkloadResolver = new(); private bool _shouldLog = false; @@ -68,6 +70,7 @@ private sealed class CachedState public string? GlobalJsonPath; public IDictionary? PropertiesToAdd; public CachingWorkloadResolver? WorkloadResolver; + public IDictionary? EnvironmentVariablesToAdd; } public override SdkResult? Resolve(SdkReference sdkReference, SdkResolverContext context, SdkResultFactory factory) @@ -78,6 +81,7 @@ private sealed class CachedState string? globalJsonPath = null; IDictionary? propertiesToAdd = null; IDictionary? itemsToAdd = null; + IDictionary? environmentVariablesToAdd = null; List? warnings = null; CachingWorkloadResolver? workloadResolver = null; @@ -99,6 +103,7 @@ private sealed class CachedState globalJsonPath = priorResult.GlobalJsonPath; propertiesToAdd = priorResult.PropertiesToAdd; workloadResolver = priorResult.WorkloadResolver; + environmentVariablesToAdd = priorResult.EnvironmentVariablesToAdd; logger?.LogMessage($"\tDotnet root: {dotnetRoot}"); logger?.LogMessage($"\tMSBuild SDKs Dir: {msbuildSdksDir}"); @@ -139,9 +144,9 @@ private sealed class CachedState logger?.LogMessage($"\tResolved SDK directory: {resolverResult.ResolvedSdkDirectory}"); logger?.LogMessage($"\tglobal.json path: {resolverResult.GlobalJsonPath}"); logger?.LogMessage($"\tFailed to resolve SDK from global.json: {resolverResult.FailedToResolveSDKSpecifiedInGlobalJson}"); - - msbuildSdksDir = Path.Combine(resolverResult.ResolvedSdkDirectory, "Sdks"); - netcoreSdkVersion = new DirectoryInfo(resolverResult.ResolvedSdkDirectory).Name; + string dotnetSdkDir = resolverResult.ResolvedSdkDirectory; + msbuildSdksDir = Path.Combine(dotnetSdkDir, "Sdks"); + netcoreSdkVersion = new DirectoryInfo(dotnetSdkDir).Name; globalJsonPath = resolverResult.GlobalJsonPath; // These are overrides that are used to force the resolved SDK tasks and targets to come from a given @@ -197,20 +202,22 @@ private sealed class CachedState } string? fullPathToMuxer = - TryResolveMuxerFromSdkResolution(resolverResult) + TryResolveMuxerFromSdkResolution(dotnetSdkDir) ?? Path.Combine(dotnetRoot, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Constants.DotNetExe : Constants.DotNet); if (File.Exists(fullPathToMuxer)) { - propertiesToAdd ??= new Dictionary(); - propertiesToAdd.Add(DotnetHostExperimentalKey, fullPathToMuxer); + environmentVariablesToAdd ??= new Dictionary(1) + { + [DOTNET_HOST] = fullPathToMuxer + }; } else { - logger?.LogMessage($"Could not set '{DotnetHostExperimentalKey}' because dotnet executable '{fullPathToMuxer}' does not exist."); + logger?.LogMessage($"Could not set '{DOTNET_HOST}' environment variable because dotnet executable '{fullPathToMuxer}' does not exist."); } string? runtimeVersion = dotnetRoot != null ? - _getMsbuildRuntime(resolverResult.ResolvedSdkDirectory, dotnetRoot) : + _getMsbuildRuntime(dotnetSdkDir, dotnetRoot) : null; if (!string.IsNullOrEmpty(runtimeVersion)) { @@ -224,7 +231,7 @@ private sealed class CachedState if (resolverResult.FailedToResolveSDKSpecifiedInGlobalJson) { - logger?.LogMessage($"Could not resolve SDK specified in '{resolverResult.GlobalJsonPath}'. Ignoring global.json for this resolution."); + logger?.LogMessage($"Could not resolve SDK specified in '{globalJsonPath}'. Ignoring global.json for this resolution."); if (warnings == null) { @@ -241,8 +248,9 @@ private sealed class CachedState } propertiesToAdd ??= new Dictionary(); - propertiesToAdd.Add("SdkResolverHonoredGlobalJson", "false"); - propertiesToAdd.Add("SdkResolverGlobalJsonPath", resolverResult.GlobalJsonPath); + propertiesToAdd.Add(SdkResolverHonoredGlobalJson, "false"); + // TODO: this would ideally be reported anytime it was non-null - that may cause more imports though? + propertiesToAdd.Add(SdkResolverGlobalJsonPath, globalJsonPath); if (logger != null) { @@ -258,7 +266,8 @@ private sealed class CachedState NETCoreSdkVersion = netcoreSdkVersion, GlobalJsonPath = globalJsonPath, PropertiesToAdd = propertiesToAdd, - WorkloadResolver = workloadResolver + WorkloadResolver = workloadResolver, + EnvironmentVariablesToAdd = environmentVariablesToAdd }; // First check if requested SDK resolves to a workload SDK pack @@ -285,7 +294,7 @@ private sealed class CachedState msbuildSdkDir); } - return factory.IndicateSuccess(msbuildSdkDir, netcoreSdkVersion, propertiesToAdd, itemsToAdd, warnings); + return factory.IndicateSuccess(msbuildSdkDir, netcoreSdkVersion, propertiesToAdd, itemsToAdd, warnings, environmentVariablesToAdd: environmentVariablesToAdd); } /// @@ -295,10 +304,10 @@ private sealed class CachedState /// SDK layouts always have a defined relationship to the location of the muxer - /// the muxer binary should be exactly two directories above the SDK directory. /// - private static string? TryResolveMuxerFromSdkResolution(SdkResolutionResult resolverResult) + private static string? TryResolveMuxerFromSdkResolution(string resolvedSdkDirectory) { var expectedFileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Constants.DotNetExe : Constants.DotNet; - var currentDir = resolverResult.ResolvedSdkDirectory; + var currentDir = resolvedSdkDirectory; var expectedDotnetRoot = Path.GetDirectoryName(Path.GetDirectoryName(currentDir)); var expectedMuxerPath = Path.Combine(expectedDotnetRoot, expectedFileName); if (File.Exists(expectedMuxerPath)) diff --git a/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnMSBuildSdkResolver.cs b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnMSBuildSdkResolver.cs index cebe1a8152b8..13fcda205ddc 100644 --- a/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnMSBuildSdkResolver.cs +++ b/test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnMSBuildSdkResolver.cs @@ -205,8 +205,14 @@ public void ItReturnsHighestSdkAvailableThatIsCompatibleWithMSBuild(bool disallo if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // DotnetHost is the path to dotnet.exe. Can be only on Windows. - result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(2); - result.PropertiesToAdd.Should().ContainKey(DotnetHostExperimentalKey); + result.PropertiesToAdd.Should().NotBeNull() + .And.HaveCount(1) + .And.NotContainKey(DotnetHostExperimentalKey); + result.EnvironmentVariablesToAdd.Should().NotBeNull() + .And.BeEquivalentTo(new Dictionary + { + ["DOTNET_HOST"] = Path.Combine(environment.GetProgramFilesDirectory(ProgramFiles.X64).FullName, "dotnet", "dotnet.exe") + }); } else { @@ -231,9 +237,9 @@ public void WhenALocalSdkIsResolvedItReturnsHostFromThatSDKInsteadOfAmbientGloba var localSdkRoot = Path.Combine("some", "local", "dir"); var localSdkDotnetRoot = Path.Combine(environment.TestDirectory.FullName, localSdkRoot, "dotnet"); var ambientSdkDotnetRoot = Path.Combine(environment.GetProgramFilesDirectory(ProgramFiles.X64).FullName, "dotnet"); - var ambientMSBuildSkRoot = environment.CreateSdkDirectory(ProgramFiles.X64, "Some.Test.Sdk", "1.2.3"); - var localPathMSBuildSdkRoot = environment.CreateSdkDirectory(localSdkRoot, "Some.Test.Sdk", "1.2.4"); - var ambientDotnetBinary = environment.CreateMuxerAndAddToPath(ProgramFiles.X64); + var _ambientMSBuildSkRoot = environment.CreateSdkDirectory(ProgramFiles.X64, "Some.Test.Sdk", "1.2.3"); + var _localPathMSBuildSdkRoot = environment.CreateSdkDirectory(localSdkRoot, "Some.Test.Sdk", "1.2.4"); + var _ambientDotnetBinary = environment.CreateMuxerAndAddToPath(ProgramFiles.X64); var localDotnetBinary = environment.CreateMuxer(localSdkRoot); environment.CreateGlobalJson(environment.TestDirectory, "1.2.3", [localSdkDotnetRoot, ambientSdkDotnetRoot]); @@ -249,9 +255,11 @@ public void WhenALocalSdkIsResolvedItReturnsHostFromThatSDKInsteadOfAmbientGloba context, new MockFactory()); result.Success.Should().BeTrue(); - result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(2); - result.PropertiesToAdd.Should().ContainKey(DotnetHostExperimentalKey); - result.PropertiesToAdd[DotnetHostExperimentalKey].Should().Be(localDotnetBinary); + result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(1).And.ContainKey(MSBuildTaskHostRuntimeVersion); + result.EnvironmentVariablesToAdd.Should().NotBeNull().And.BeEquivalentTo(new Dictionary + { + [DotnetHostExperimentalKey] = localDotnetBinary + }); } [Theory] @@ -325,8 +333,13 @@ public void ItReturnsHighestSdkAvailableThatIsCompatibleWithMSBuildWhenVersionIn if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // DotnetHost is the path to dotnet.exe. Can be only on Windows. - result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(4); - result.PropertiesToAdd.Should().ContainKey(DotnetHostExperimentalKey); + result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(3); + result.PropertiesToAdd.Should().NotContainKey(DotnetHostExperimentalKey); + result.EnvironmentVariablesToAdd.Should().NotBeNull() + .And.BeEquivalentTo(new Dictionary + { + ["DOTNET_HOST"] = Path.Combine(environment.GetProgramFilesDirectory(ProgramFiles.X64).FullName, "dotnet", "dotnet.exe") + }); } else {