Skip to content

Commit ea55de9

Browse files
committed
set env vars from resolver APIs
1 parent 61825e3 commit ea55de9

File tree

2 files changed

+48
-26
lines changed

2 files changed

+48
-26
lines changed

src/Resolvers/Microsoft.DotNet.MSBuildSdkResolver/MSBuildSdkResolver.cs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ public sealed class DotNetMSBuildSdkResolver : SdkResolver
3232
private readonly Func<string, string, string?> _getMsbuildRuntime;
3333
private readonly NETCoreSdkResolver _netCoreSdkResolver;
3434

35+
private const string DOTNET_HOST = nameof(DOTNET_HOST);
3536
private const string DotnetHostExperimentalKey = "DOTNET_EXPERIMENTAL_HOST_PATH";
3637
private const string MSBuildTaskHostRuntimeVersion = "SdkResolverMSBuildTaskHostRuntimeVersion";
37-
38+
private const string SdkResolverHonoredGlobalJson = "SdkResolverHonoredGlobalJson";
39+
private const string SdkResolverGlobalJsonPath = "SdkResolverGlobalJsonPath";
3840
private static CachingWorkloadResolver _staticWorkloadResolver = new();
3941

4042
private bool _shouldLog = false;
@@ -68,6 +70,7 @@ private sealed class CachedState
6870
public string? GlobalJsonPath;
6971
public IDictionary<string, string?>? PropertiesToAdd;
7072
public CachingWorkloadResolver? WorkloadResolver;
73+
public IDictionary<string, string?>? EnvironmentVariablesToAdd;
7174
}
7275

7376
public override SdkResult? Resolve(SdkReference sdkReference, SdkResolverContext context, SdkResultFactory factory)
@@ -78,6 +81,7 @@ private sealed class CachedState
7881
string? globalJsonPath = null;
7982
IDictionary<string, string?>? propertiesToAdd = null;
8083
IDictionary<string, SdkResultItem>? itemsToAdd = null;
84+
IDictionary<string, string?>? environmentVariablesToAdd = null;
8185
List<string>? warnings = null;
8286
CachingWorkloadResolver? workloadResolver = null;
8387

@@ -99,6 +103,7 @@ private sealed class CachedState
99103
globalJsonPath = priorResult.GlobalJsonPath;
100104
propertiesToAdd = priorResult.PropertiesToAdd;
101105
workloadResolver = priorResult.WorkloadResolver;
106+
environmentVariablesToAdd = priorResult.EnvironmentVariablesToAdd;
102107

103108
logger?.LogMessage($"\tDotnet root: {dotnetRoot}");
104109
logger?.LogMessage($"\tMSBuild SDKs Dir: {msbuildSdksDir}");
@@ -139,9 +144,9 @@ private sealed class CachedState
139144
logger?.LogMessage($"\tResolved SDK directory: {resolverResult.ResolvedSdkDirectory}");
140145
logger?.LogMessage($"\tglobal.json path: {resolverResult.GlobalJsonPath}");
141146
logger?.LogMessage($"\tFailed to resolve SDK from global.json: {resolverResult.FailedToResolveSDKSpecifiedInGlobalJson}");
142-
143-
msbuildSdksDir = Path.Combine(resolverResult.ResolvedSdkDirectory, "Sdks");
144-
netcoreSdkVersion = new DirectoryInfo(resolverResult.ResolvedSdkDirectory).Name;
147+
string dotnetSdkDir = resolverResult.ResolvedSdkDirectory;
148+
msbuildSdksDir = Path.Combine(dotnetSdkDir, "Sdks");
149+
netcoreSdkVersion = new DirectoryInfo(dotnetSdkDir).Name;
145150
globalJsonPath = resolverResult.GlobalJsonPath;
146151

147152
// 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
197202
}
198203

199204
string? fullPathToMuxer =
200-
TryResolveMuxerFromSdkResolution(resolverResult)
205+
TryResolveMuxerFromSdkResolution(dotnetSdkDir)
201206
?? Path.Combine(dotnetRoot, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Constants.DotNetExe : Constants.DotNet);
202207
if (File.Exists(fullPathToMuxer))
203208
{
204-
propertiesToAdd ??= new Dictionary<string, string?>();
205-
propertiesToAdd.Add(DotnetHostExperimentalKey, fullPathToMuxer);
209+
environmentVariablesToAdd ??= new Dictionary<string, string?>(1)
210+
{
211+
[DOTNET_HOST] = fullPathToMuxer
212+
};
206213
}
207214
else
208215
{
209-
logger?.LogMessage($"Could not set '{DotnetHostExperimentalKey}' because dotnet executable '{fullPathToMuxer}' does not exist.");
216+
logger?.LogMessage($"Could not set '{DOTNET_HOST}' environment variable because dotnet executable '{fullPathToMuxer}' does not exist.");
210217
}
211218

212219
string? runtimeVersion = dotnetRoot != null ?
213-
_getMsbuildRuntime(resolverResult.ResolvedSdkDirectory, dotnetRoot) :
220+
_getMsbuildRuntime(dotnetSdkDir, dotnetRoot) :
214221
null;
215222
if (!string.IsNullOrEmpty(runtimeVersion))
216223
{
@@ -224,7 +231,7 @@ private sealed class CachedState
224231

225232
if (resolverResult.FailedToResolveSDKSpecifiedInGlobalJson)
226233
{
227-
logger?.LogMessage($"Could not resolve SDK specified in '{resolverResult.GlobalJsonPath}'. Ignoring global.json for this resolution.");
234+
logger?.LogMessage($"Could not resolve SDK specified in '{globalJsonPath}'. Ignoring global.json for this resolution.");
228235

229236
if (warnings == null)
230237
{
@@ -241,8 +248,9 @@ private sealed class CachedState
241248
}
242249

243250
propertiesToAdd ??= new Dictionary<string, string?>();
244-
propertiesToAdd.Add("SdkResolverHonoredGlobalJson", "false");
245-
propertiesToAdd.Add("SdkResolverGlobalJsonPath", resolverResult.GlobalJsonPath);
251+
propertiesToAdd.Add(SdkResolverHonoredGlobalJson, "false");
252+
// TODO: this would ideally be reported anytime it was non-null - that may cause more imports though?
253+
propertiesToAdd.Add(SdkResolverGlobalJsonPath, globalJsonPath);
246254

247255
if (logger != null)
248256
{
@@ -258,7 +266,8 @@ private sealed class CachedState
258266
NETCoreSdkVersion = netcoreSdkVersion,
259267
GlobalJsonPath = globalJsonPath,
260268
PropertiesToAdd = propertiesToAdd,
261-
WorkloadResolver = workloadResolver
269+
WorkloadResolver = workloadResolver,
270+
EnvironmentVariablesToAdd = environmentVariablesToAdd
262271
};
263272

264273
// First check if requested SDK resolves to a workload SDK pack
@@ -285,7 +294,7 @@ private sealed class CachedState
285294
msbuildSdkDir);
286295
}
287296

288-
return factory.IndicateSuccess(msbuildSdkDir, netcoreSdkVersion, propertiesToAdd, itemsToAdd, warnings);
297+
return factory.IndicateSuccess(msbuildSdkDir, netcoreSdkVersion, propertiesToAdd, itemsToAdd, warnings, environmentVariablesToAdd: environmentVariablesToAdd);
289298
}
290299

291300
/// <summary>
@@ -295,10 +304,10 @@ private sealed class CachedState
295304
/// SDK layouts always have a defined relationship to the location of the muxer -
296305
/// the muxer binary should be exactly two directories above the SDK directory.
297306
/// </remarks>
298-
private static string? TryResolveMuxerFromSdkResolution(SdkResolutionResult resolverResult)
307+
private static string? TryResolveMuxerFromSdkResolution(string resolvedSdkDirectory)
299308
{
300309
var expectedFileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Constants.DotNetExe : Constants.DotNet;
301-
var currentDir = resolverResult.ResolvedSdkDirectory;
310+
var currentDir = resolvedSdkDirectory;
302311
var expectedDotnetRoot = Path.GetDirectoryName(Path.GetDirectoryName(currentDir));
303312
var expectedMuxerPath = Path.Combine(expectedDotnetRoot, expectedFileName);
304313
if (File.Exists(expectedMuxerPath))

test/Microsoft.DotNet.MSBuildSdkResolver.Tests/GivenAnMSBuildSdkResolver.cs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,14 @@ public void ItReturnsHighestSdkAvailableThatIsCompatibleWithMSBuild(bool disallo
205205
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
206206
{
207207
// DotnetHost is the path to dotnet.exe. Can be only on Windows.
208-
result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(2);
209-
result.PropertiesToAdd.Should().ContainKey(DotnetHostExperimentalKey);
208+
result.PropertiesToAdd.Should().NotBeNull()
209+
.And.HaveCount(1)
210+
.And.NotContainKey(DotnetHostExperimentalKey);
211+
result.EnvironmentVariablesToAdd.Should().NotBeNull()
212+
.And.BeEquivalentTo(new Dictionary<string, string?>
213+
{
214+
["DOTNET_HOST"] = Path.Combine(environment.GetProgramFilesDirectory(ProgramFiles.X64).FullName, "dotnet", "dotnet.exe")
215+
});
210216
}
211217
else
212218
{
@@ -231,9 +237,9 @@ public void WhenALocalSdkIsResolvedItReturnsHostFromThatSDKInsteadOfAmbientGloba
231237
var localSdkRoot = Path.Combine("some", "local", "dir");
232238
var localSdkDotnetRoot = Path.Combine(environment.TestDirectory.FullName, localSdkRoot, "dotnet");
233239
var ambientSdkDotnetRoot = Path.Combine(environment.GetProgramFilesDirectory(ProgramFiles.X64).FullName, "dotnet");
234-
var ambientMSBuildSkRoot = environment.CreateSdkDirectory(ProgramFiles.X64, "Some.Test.Sdk", "1.2.3");
235-
var localPathMSBuildSdkRoot = environment.CreateSdkDirectory(localSdkRoot, "Some.Test.Sdk", "1.2.4");
236-
var ambientDotnetBinary = environment.CreateMuxerAndAddToPath(ProgramFiles.X64);
240+
var _ambientMSBuildSkRoot = environment.CreateSdkDirectory(ProgramFiles.X64, "Some.Test.Sdk", "1.2.3");
241+
var _localPathMSBuildSdkRoot = environment.CreateSdkDirectory(localSdkRoot, "Some.Test.Sdk", "1.2.4");
242+
var _ambientDotnetBinary = environment.CreateMuxerAndAddToPath(ProgramFiles.X64);
237243
var localDotnetBinary = environment.CreateMuxer(localSdkRoot);
238244
environment.CreateGlobalJson(environment.TestDirectory, "1.2.3", [localSdkDotnetRoot, ambientSdkDotnetRoot]);
239245

@@ -249,9 +255,11 @@ public void WhenALocalSdkIsResolvedItReturnsHostFromThatSDKInsteadOfAmbientGloba
249255
context,
250256
new MockFactory());
251257
result.Success.Should().BeTrue();
252-
result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(2);
253-
result.PropertiesToAdd.Should().ContainKey(DotnetHostExperimentalKey);
254-
result.PropertiesToAdd[DotnetHostExperimentalKey].Should().Be(localDotnetBinary);
258+
result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(1).And.ContainKey(MSBuildTaskHostRuntimeVersion);
259+
result.EnvironmentVariablesToAdd.Should().NotBeNull().And.BeEquivalentTo(new Dictionary<string, string?>
260+
{
261+
[DotnetHostExperimentalKey] = localDotnetBinary
262+
});
255263
}
256264

257265
[Theory]
@@ -325,8 +333,13 @@ public void ItReturnsHighestSdkAvailableThatIsCompatibleWithMSBuildWhenVersionIn
325333
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
326334
{
327335
// DotnetHost is the path to dotnet.exe. Can be only on Windows.
328-
result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(4);
329-
result.PropertiesToAdd.Should().ContainKey(DotnetHostExperimentalKey);
336+
result.PropertiesToAdd.Should().NotBeNull().And.HaveCount(3);
337+
result.PropertiesToAdd.Should().NotContainKey(DotnetHostExperimentalKey);
338+
result.EnvironmentVariablesToAdd.Should().NotBeNull()
339+
.And.BeEquivalentTo(new Dictionary<string, string?>
340+
{
341+
["DOTNET_HOST"] = Path.Combine(environment.GetProgramFilesDirectory(ProgramFiles.X64).FullName, "dotnet", "dotnet.exe")
342+
});
330343
}
331344
else
332345
{

0 commit comments

Comments
 (0)