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

Expand usingtask customization #7550

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions src/Build.UnitTests/BuildEnvironmentHelper_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ public void BuildEnvironmentFindsAmd64()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/msbuild/issues/7552", TargetFrameworkMonikers.Any)]
[PlatformSpecific(TestPlatforms.Windows)]
public void BuildEnvironmentFindsAmd64RunningInAmd64NoVS()
{
Expand All @@ -386,6 +387,7 @@ public void BuildEnvironmentFindsAmd64RunningInAmd64NoVS()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/msbuild/issues/7552", TargetFrameworkMonikers.Any)]
[PlatformSpecific(TestPlatforms.Windows)]
public void BuildEnvironmentFindsAmd64NoVS()
{
Expand All @@ -401,6 +403,7 @@ public void BuildEnvironmentFindsAmd64NoVS()
}

[Fact]
[ActiveIssue("https://github.com/dotnet/msbuild/issues/7552", TargetFrameworkMonikers.Any)]
[SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp, "No Visual Studio install for netcore")]
[PlatformSpecific(TestPlatforms.Windows)]
public void BuildEnvironmentFindsAmd64RunningInAmd64()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ internal NodeEndpointOutOfProc(
/// </summary>
protected override Handshake GetHandshake()
{
return new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, is64Bit: EnvironmentUtilities.Is64BitProcess, nodeReuse: _enableReuse, lowPriority: _lowPriority));
return new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, architectureFlagToSet: XMakeAttributes.GetCurrentMSBuildArchitecture(), nodeReuse: _enableReuse, lowPriority: _lowPriority));
}

#region Structs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public int AvailableNodes
internal static Handshake GetHandshake(bool enableNodeReuse, bool enableLowPriority)
{
CommunicationsUtilities.Trace("MSBUILDNODEHANDSHAKESALT=\"{0}\", msbuildDirectory=\"{1}\", enableNodeReuse={2}, enableLowPriority={3}", Traits.MSBuildNodeHandshakeSalt, BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32, enableNodeReuse, enableLowPriority);
return new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, nodeReuse: enableNodeReuse, lowPriority: enableLowPriority, is64Bit: EnvironmentUtilities.Is64BitProcess));
return new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, architectureFlagToSet: XMakeAttributes.GetCurrentMSBuildArchitecture(), nodeReuse: enableNodeReuse, lowPriority: enableLowPriority));
}

/// <summary>
Expand All @@ -94,7 +94,7 @@ public bool CreateNode(int nodeId, INodePacketFactory factory, NodeConfiguration
// Make it here.
CommunicationsUtilities.Trace("Starting to acquire a new or existing node to establish node ID {0}...", nodeId);

Handshake hostHandshake = new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, nodeReuse: ComponentHost.BuildParameters.EnableNodeReuse, lowPriority: ComponentHost.BuildParameters.LowPriority, is64Bit: EnvironmentUtilities.Is64BitProcess));
Handshake hostHandshake = new Handshake(CommunicationsUtilities.GetHandshakeOptions(taskHost: false, architectureFlagToSet: XMakeAttributes.GetCurrentMSBuildArchitecture(), nodeReuse: ComponentHost.BuildParameters.EnableNodeReuse, lowPriority: ComponentHost.BuildParameters.LowPriority));
NodeContext context = GetNode(null, commandLineArgs, nodeId, factory, hostHandshake, NodeContextTerminated);

if (context != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ internal class NodeProviderOutOfProcTaskHost : NodeProviderOutOfProcBase, INodeP
/// </summary>
private static string s_baseTaskHostPath64;

/// <summary>
/// Store the 64-bit path for MSBuild / MSBuildTaskHost so that we don't have to keep recalculating it.
/// </summary>
private static string s_baseTaskHostPathArm64;

/// <summary>
/// Store the path for the 32-bit MSBuildTaskHost so that we don't have to keep re-calculating it.
/// </summary>
Expand All @@ -57,6 +62,11 @@ internal class NodeProviderOutOfProcTaskHost : NodeProviderOutOfProcBase, INodeP
/// </summary>
private static string s_pathToX64Clr4;

/// <summary>
/// Store the path for the 64-bit MSBuild so that we don't have to keep re-calculating it.
/// </summary>
private static string s_pathToArm64Clr4;

/// <summary>
/// Name for MSBuild.exe
/// </summary>
Expand Down Expand Up @@ -353,8 +363,10 @@ internal static void ClearCachedTaskHostPaths()
s_pathToX32Clr4 = null;
s_pathToX64Clr2 = null;
s_pathToX64Clr4 = null;
s_pathToArm64Clr4 = null;
s_baseTaskHostPath = null;
s_baseTaskHostPath64 = null;
s_baseTaskHostPathArm64 = null;
}

/// <summary>
Expand Down Expand Up @@ -392,13 +404,20 @@ internal static string GetTaskHostNameFromHostContext(HandshakeOptions hostConte
internal static string GetMSBuildLocationFromHostContext(HandshakeOptions hostContext)
{
string toolName = GetTaskHostNameFromHostContext(hostContext);
string toolPath;
string toolPath = null;

s_baseTaskHostPath = BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32;
s_baseTaskHostPath64 = BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64;
s_baseTaskHostPathArm64 = BuildEnvironmentHelper.Instance.MSBuildToolsDirectoryArm64;

ErrorUtilities.VerifyThrowInternalErrorUnreachable((hostContext & HandshakeOptions.TaskHost) == HandshakeOptions.TaskHost);

if ((hostContext & HandshakeOptions.X64) == HandshakeOptions.X64 && (hostContext & HandshakeOptions.CLR2) == HandshakeOptions.CLR2)
if ((hostContext & HandshakeOptions.Arm64) == HandshakeOptions.Arm64 && (hostContext & HandshakeOptions.CLR2) == HandshakeOptions.CLR2)
{
// Unsupported, throw.
ErrorUtilities.ThrowInternalError("ARM64 CLR2 task hosts are not supported.");
}
else if ((hostContext & HandshakeOptions.X64) == HandshakeOptions.X64 && (hostContext & HandshakeOptions.CLR2) == HandshakeOptions.CLR2)
{
if (s_pathToX64Clr2 == null)
{
Expand Down Expand Up @@ -434,6 +453,15 @@ internal static string GetMSBuildLocationFromHostContext(HandshakeOptions hostCo

toolPath = s_pathToX64Clr4;
}
else if ((hostContext & HandshakeOptions.Arm64) == HandshakeOptions.Arm64)
{
if (s_pathToArm64Clr4 == null)
{
s_pathToArm64Clr4 = s_baseTaskHostPathArm64;
}

toolPath = s_pathToArm64Clr4;
}
else
{
if (s_pathToX32Clr4 == null)
Expand Down
62 changes: 35 additions & 27 deletions src/Shared/BuildEnvironmentHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;

using Microsoft.Build.Framework;
using Microsoft.Build.Shared.FileSystem;
using System.Reflection;

Expand Down Expand Up @@ -531,42 +532,38 @@ public BuildEnvironment(BuildEnvironmentMode mode, string currentMSBuildExePath,
if (mode == BuildEnvironmentMode.None || currentMSBuildExeFile == null || currentToolsDirectory == null)
return;

// Check to see if our current folder is 'amd64'
bool runningInAmd64 = string.Equals(currentToolsDirectory.Name, "amd64", StringComparison.OrdinalIgnoreCase);
bool runningInARM64 = string.Equals(currentToolsDirectory.Name, "arm64", StringComparison.OrdinalIgnoreCase);

var msBuildExeName = currentMSBuildExeFile.Name;
var folderAbove = currentToolsDirectory.Parent?.FullName;

if (folderAbove != null)
if (mode == BuildEnvironmentMode.VisualStudio)
{
// In Visual Studio, the entry-point MSBuild.exe is often from an arch-specific subfolder
MSBuildToolsDirectoryRoot = NativeMethodsShared.ProcessorArchitecture switch
{
NativeMethodsShared.ProcessorArchitectures.X86 => CurrentMSBuildToolsDirectory,
NativeMethodsShared.ProcessorArchitectures.X64 or NativeMethodsShared.ProcessorArchitectures.ARM64
=> currentToolsDirectory.Parent?.FullName,
_ => throw new InternalErrorException("Unknown processor architecture " + NativeMethodsShared.ProcessorArchitecture),
};
}
else
{
// In the .NET SDK, there's one copy of MSBuild.dll and it's in the root folder.
MSBuildToolsDirectoryRoot = CurrentMSBuildToolsDirectory;
}

if (mode == BuildEnvironmentMode.VisualStudio && MSBuildToolsDirectoryRoot != null)
{
// Calculate potential paths to other architecture MSBuild.exe
var potentialAmd64FromX86 = FileUtilities.CombinePaths(CurrentMSBuildToolsDirectory, "amd64", msBuildExeName);
var potentialARM64FromX86 = FileUtilities.CombinePaths(CurrentMSBuildToolsDirectory, "arm64", msBuildExeName);
var potentialX86FromAmd64 = Path.Combine(folderAbove, msBuildExeName);
var potentialAmd64FromX86 = FileUtilities.CombinePaths(MSBuildToolsDirectoryRoot, "amd64", msBuildExeName);
var potentialARM64FromX86 = FileUtilities.CombinePaths(MSBuildToolsDirectoryRoot, "arm64", msBuildExeName);

// Check for existence of an MSBuild file. Note this is not necessary in a VS installation where we always want to
// assume the correct layout.
var existsCheck = mode == BuildEnvironmentMode.VisualStudio ? new Func<string, bool>(_ => true) : File.Exists;

if ((runningInARM64 || runningInAmd64) && existsCheck(potentialX86FromAmd64))
{
MSBuildToolsDirectory32 = folderAbove;
MSBuildToolsDirectory64 = CurrentMSBuildToolsDirectory;
}
else if (!runningInAmd64 && !runningInARM64)
{
MSBuildToolsDirectory32 = CurrentMSBuildToolsDirectory;

if (existsCheck(potentialARM64FromX86) && NativeMethodsShared.ProcessorArchitecture == Framework.NativeMethods.ProcessorArchitectures.ARM64)
{
MSBuildToolsDirectory64 = Path.Combine(CurrentMSBuildToolsDirectory, "arm64");
}
else if (existsCheck(potentialAmd64FromX86))
{
MSBuildToolsDirectory64 = Path.Combine(CurrentMSBuildToolsDirectory, "amd64");
}
}
MSBuildToolsDirectory32 = MSBuildToolsDirectoryRoot;
MSBuildToolsDirectory64 = Path.Combine(MSBuildToolsDirectoryRoot, "amd64");
MSBuildToolsDirectoryArm64 = File.Exists(potentialARM64FromX86) ? Path.Combine(MSBuildToolsDirectoryRoot, "arm64") : null;
}

MSBuildExtensionsPath = mode == BuildEnvironmentMode.VisualStudio
Expand All @@ -586,6 +583,11 @@ public BuildEnvironment(BuildEnvironmentMode mode, string currentMSBuildExePath,
/// </summary>
internal bool RunningInVisualStudio { get; }

/// <summary>
/// Path to the root of the MSBuild folder (in VS scenarios, <c>MSBuild\Current\bin</c>).
/// </summary>
internal string MSBuildToolsDirectoryRoot { get; }

/// <summary>
/// Path to the MSBuild 32-bit tools directory.
/// </summary>
Expand All @@ -596,6 +598,12 @@ public BuildEnvironment(BuildEnvironmentMode mode, string currentMSBuildExePath,
/// </summary>
internal string MSBuildToolsDirectory64 { get; }

/// <summary>
/// Path to the ARM64 tools directory.
/// <see langword="null" /> if ARM64 tools are not installed.
/// </summary>
internal string MSBuildToolsDirectoryArm64 { get; }

/// <summary>
/// Path to the Sdks folder for this MSBuild instance.
/// </summary>
Expand Down
34 changes: 23 additions & 11 deletions src/Shared/CommunicationsUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ internal enum HandshakeOptions
/// Using the .NET Core/.NET 5.0+ runtime
/// </summary>
NET = 64,

/// <summary>
/// ARM64 process
/// </summary>
Arm64 = 128,
}

internal readonly struct Handshake
Expand All @@ -90,9 +95,9 @@ internal Handshake(HandshakeOptions nodeType)
CommunicationsUtilities.Trace("Building handshake for node type {0}, (version {1}): options {2}.", nodeType, handshakeVersion, options);

string handshakeSalt = Environment.GetEnvironmentVariable("MSBUILDNODEHANDSHAKESALT");
CommunicationsUtilities.Trace("Handshake salt is \"{0}\"", handshakeSalt);
string toolsDirectory = (nodeType & HandshakeOptions.X64) == HandshakeOptions.X64 ? BuildEnvironmentHelper.Instance.MSBuildToolsDirectory64 : BuildEnvironmentHelper.Instance.MSBuildToolsDirectory32;
CommunicationsUtilities.Trace("Tools directory is \"{0}\"", toolsDirectory);
CommunicationsUtilities.Trace("Handshake salt is " + handshakeSalt);
string toolsDirectory = BuildEnvironmentHelper.Instance.MSBuildToolsDirectoryRoot;
CommunicationsUtilities.Trace("Tools directory root is " + toolsDirectory);
salt = CommunicationsUtilities.GetHashCode(handshakeSalt + toolsDirectory);
Version fileVersion = new Version(FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion);
fileVersionMajor = fileVersion.Major;
Expand Down Expand Up @@ -483,22 +488,22 @@ internal static async Task<int> ReadAsync(Stream stream, byte[] buffer, int byte
/// <summary>
/// Given the appropriate information, return the equivalent HandshakeOptions.
/// </summary>
internal static HandshakeOptions GetHandshakeOptions(bool taskHost, bool is64Bit = false, bool nodeReuse = false, bool lowPriority = false, IDictionary<string, string> taskHostParameters = null)
internal static HandshakeOptions GetHandshakeOptions(bool taskHost, string architectureFlagToSet = null, bool nodeReuse = false, bool lowPriority = false, IDictionary<string, string> taskHostParameters = null)
{
HandshakeOptions context = taskHost ? HandshakeOptions.TaskHost : HandshakeOptions.None;

int clrVersion = 0;

// We don't know about the TaskHost. Figure it out.
// We don't know about the TaskHost.
if (taskHost)
{
// Take the current TaskHost context
// No parameters given, default to current
if (taskHostParameters == null)
{
clrVersion = typeof(bool).GetTypeInfo().Assembly.GetName().Version.Major;
is64Bit = XMakeAttributes.GetCurrentMSBuildArchitecture().Equals(XMakeAttributes.MSBuildArchitectureValues.x64);
architectureFlagToSet = XMakeAttributes.GetCurrentMSBuildArchitecture();
}
else
else // Figure out flags based on parameters given
{
ErrorUtilities.VerifyThrow(taskHostParameters.TryGetValue(XMakeAttributes.runtime, out string runtimeVersion), "Should always have an explicit runtime when we call this method.");
ErrorUtilities.VerifyThrow(taskHostParameters.TryGetValue(XMakeAttributes.architecture, out string architecture), "Should always have an explicit architecture when we call this method.");
Expand All @@ -520,13 +525,20 @@ internal static HandshakeOptions GetHandshakeOptions(bool taskHost, bool is64Bit
ErrorUtilities.ThrowInternalErrorUnreachable();
}

is64Bit = architecture.Equals(XMakeAttributes.MSBuildArchitectureValues.x64);
architectureFlagToSet = architecture;
}
}

if (is64Bit)
if (!string.IsNullOrEmpty(architectureFlagToSet))
{
context |= HandshakeOptions.X64;
if (architectureFlagToSet.Equals(XMakeAttributes.MSBuildArchitectureValues.x64, StringComparison.OrdinalIgnoreCase))
{
context |= HandshakeOptions.X64;
}
else if (architectureFlagToSet.Equals(XMakeAttributes.MSBuildArchitectureValues.arm64, StringComparison.OrdinalIgnoreCase))
{
context |= HandshakeOptions.Arm64;
}
}

switch (clrVersion)
Expand Down
24 changes: 23 additions & 1 deletion src/Shared/XMakeAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

using System;
using System.Collections.Generic;
#if !CLR2COMPATIBILITY
using System.Runtime.InteropServices;
#endif
using System.Runtime.CompilerServices;

#nullable disable
Expand Down Expand Up @@ -88,6 +91,7 @@ internal struct MSBuildArchitectureValues
{
internal const string x86 = "x86";
internal const string x64 = "x64";
internal const string arm64 = "arm64";
internal const string currentArchitecture = "CurrentArchitecture";
internal const string any = "*";
}
Expand All @@ -106,7 +110,7 @@ internal struct MSBuildArchitectureValues

private static readonly HashSet<string> ValidMSBuildRuntimeValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { MSBuildRuntimeValues.clr2, MSBuildRuntimeValues.clr4, MSBuildRuntimeValues.currentRuntime, MSBuildRuntimeValues.net, MSBuildRuntimeValues.any };

private static readonly HashSet<string> ValidMSBuildArchitectureValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { MSBuildArchitectureValues.x86, MSBuildArchitectureValues.x64, MSBuildArchitectureValues.currentArchitecture, MSBuildArchitectureValues.any };
private static readonly HashSet<string> ValidMSBuildArchitectureValues = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { MSBuildArchitectureValues.x86, MSBuildArchitectureValues.x64, MSBuildArchitectureValues.arm64, MSBuildArchitectureValues.currentArchitecture, MSBuildArchitectureValues.any };

/// <summary>
/// Returns true if and only if the specified attribute is one of the attributes that the engine specifically recognizes
Expand Down Expand Up @@ -429,7 +433,25 @@ internal static bool TryMergeArchitectureValues(string architectureA, string arc
/// </comments>
internal static string GetCurrentMSBuildArchitecture()
{
#if !CLR2COMPATIBILITY
string currentArchitecture = string.Empty;
switch (RuntimeInformation.ProcessArchitecture)
{
case Architecture.X86:
currentArchitecture = MSBuildArchitectureValues.x86;
break;
case Architecture.X64:
currentArchitecture = MSBuildArchitectureValues.x64;
break;
case Architecture.Arm64:
currentArchitecture = MSBuildArchitectureValues.arm64;
break;
default:
throw new PlatformNotSupportedException(string.Format("{0} is not a supported architecture.", RuntimeInformation.ProcessArchitecture));
}
#else
string currentArchitecture = (IntPtr.Size == sizeof(Int64)) ? MSBuildArchitectureValues.x64 : MSBuildArchitectureValues.x86;
#endif
return currentArchitecture;
}

Expand Down