VS: Detect ARM64 host architecture at runtime
We use the host machine's architecture to select the `MSBuild.exe` binary variant, and the host toolset architecture. When CMake is compiled as `x64` or `x86` it may still run on ARM64 hosts. Detect the actual architecture of the host at runtime instead of relying on the architecture of CMake's own binary. The `arm64/MSBuild.exe` executable is an ARM64 .NET 4 application, which requires the ARM64 version of .NET Framework 4.8.1 to be installed on the machine. That version is not yet released for Windows 10; however, the `MSBuild/Current/Bin/arm64` directory is still created when installing Visual Studio 2022 (a user may upgrade to Windows 11 later). Use it only if the .NET Framework is installed. The `amd64/MSBuild.exe` executable cannot run on Windows 10 ARM64, but can run on Windows 11 ARM64. Fixes: #23755
This commit is contained in:
parent
c508b3625a
commit
418fd85569
@ -25,53 +25,100 @@
|
||||
#include "cmVSSetupHelper.h"
|
||||
#include "cmake.h"
|
||||
|
||||
#if defined(_M_ARM64)
|
||||
# define HOST_PLATFORM_NAME "ARM64"
|
||||
# define HOST_TOOLS_ARCH(v) \
|
||||
(v >= cmGlobalVisualStudioGenerator::VSVersion::VS17) ? "ARM64" : ""
|
||||
#elif defined(_M_ARM)
|
||||
# define HOST_PLATFORM_NAME "ARM"
|
||||
# define HOST_TOOLS_ARCH(v) ""
|
||||
#elif defined(_M_IA64)
|
||||
# define HOST_PLATFORM_NAME "Itanium"
|
||||
# define HOST_TOOLS_ARCH(v) ""
|
||||
#elif defined(_WIN64)
|
||||
# define HOST_PLATFORM_NAME "x64"
|
||||
# define HOST_TOOLS_ARCH(v) "x64"
|
||||
#else
|
||||
#ifndef IMAGE_FILE_MACHINE_ARM64
|
||||
# define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian
|
||||
#endif
|
||||
|
||||
static bool VSIsWow64()
|
||||
{
|
||||
BOOL isWow64 = false;
|
||||
return IsWow64Process(GetCurrentProcess(), &isWow64) && isWow64;
|
||||
}
|
||||
|
||||
static bool VSIsArm64Host()
|
||||
{
|
||||
typedef BOOL(WINAPI * CM_ISWOW64PROCESS2)(
|
||||
HANDLE hProcess, USHORT * pProcessMachine, USHORT * pNativeMachine);
|
||||
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
# define CM_VS_GCC_DIAGNOSTIC_PUSHED
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
#endif
|
||||
static const CM_ISWOW64PROCESS2 s_IsWow64Process2Impl =
|
||||
(CM_ISWOW64PROCESS2)GetProcAddress(
|
||||
GetModuleHandleW(L"api-ms-win-core-wow64-l1-1-1.dll"),
|
||||
"IsWow64Process2");
|
||||
#ifdef CM_VS_GCC_DIAGNOSTIC_PUSHED
|
||||
# pragma GCC diagnostic pop
|
||||
# undef CM_VS_GCC_DIAGNOSTIC_PUSHED
|
||||
#endif
|
||||
|
||||
USHORT processMachine, nativeMachine;
|
||||
|
||||
return s_IsWow64Process2Impl != nullptr &&
|
||||
s_IsWow64Process2Impl(GetCurrentProcess(), &processMachine,
|
||||
&nativeMachine) &&
|
||||
nativeMachine == IMAGE_FILE_MACHINE_ARM64;
|
||||
}
|
||||
|
||||
static bool VSHasDotNETFrameworkArm64()
|
||||
{
|
||||
std::string dotNetArm64;
|
||||
return cmSystemTools::ReadRegistryValue(
|
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\.NETFramework;InstallRootArm64",
|
||||
dotNetArm64);
|
||||
}
|
||||
|
||||
static bool VSIsWindows11OrGreater()
|
||||
{
|
||||
cmSystemTools::WindowsVersion const windowsVersion =
|
||||
cmSystemTools::GetWindowsVersion();
|
||||
return (windowsVersion.dwMajorVersion > 10 ||
|
||||
(windowsVersion.dwMajorVersion == 10 &&
|
||||
windowsVersion.dwMinorVersion > 0) ||
|
||||
(windowsVersion.dwMajorVersion == 10 &&
|
||||
windowsVersion.dwMinorVersion == 0 &&
|
||||
windowsVersion.dwBuildNumber >= 22000));
|
||||
}
|
||||
|
||||
static std::string VSHostPlatformName()
|
||||
{
|
||||
#ifdef HOST_PLATFORM_NAME
|
||||
return HOST_PLATFORM_NAME;
|
||||
#else
|
||||
if (VSIsWow64()) {
|
||||
if (VSIsArm64Host()) {
|
||||
return "ARM64";
|
||||
} else if (VSIsWow64()) {
|
||||
return "x64";
|
||||
} else {
|
||||
#if defined(_M_ARM)
|
||||
return "ARM";
|
||||
#elif defined(_M_IA64)
|
||||
return "Itanium";
|
||||
#elif defined(_WIN64)
|
||||
return "x64";
|
||||
#else
|
||||
return "Win32";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static std::string VSHostArchitecture(
|
||||
cmGlobalVisualStudioGenerator::VSVersion v)
|
||||
{
|
||||
static_cast<void>(v);
|
||||
#ifdef HOST_TOOLS_ARCH
|
||||
return HOST_TOOLS_ARCH(v);
|
||||
#else
|
||||
if (VSIsWow64()) {
|
||||
if (VSIsArm64Host()) {
|
||||
return v >= cmGlobalVisualStudioGenerator::VSVersion::VS17 ? "ARM64" : "";
|
||||
} else if (VSIsWow64()) {
|
||||
return "x64";
|
||||
} else {
|
||||
#if defined(_M_ARM)
|
||||
return "";
|
||||
#elif defined(_M_IA64)
|
||||
return "";
|
||||
#elif defined(_WIN64)
|
||||
return "x64";
|
||||
#else
|
||||
return "x86";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int VSVersionToMajor(
|
||||
@ -899,17 +946,24 @@ std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand()
|
||||
std::string vs;
|
||||
if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) {
|
||||
if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS17) {
|
||||
#if defined(_M_ARM64)
|
||||
std::string msbuild_arm64 =
|
||||
vs + "/MSBuild/Current/Bin/arm64/MSBuild.exe";
|
||||
if (cmSystemTools::FileExists(msbuild_arm64)) {
|
||||
return msbuild_arm64;
|
||||
}
|
||||
#endif
|
||||
|
||||
msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe";
|
||||
if (cmSystemTools::FileExists(msbuild)) {
|
||||
return msbuild;
|
||||
if (VSIsArm64Host()) {
|
||||
if (VSHasDotNETFrameworkArm64()) {
|
||||
msbuild = vs + "/MSBuild/Current/Bin/arm64/MSBuild.exe";
|
||||
if (cmSystemTools::FileExists(msbuild)) {
|
||||
return msbuild;
|
||||
}
|
||||
}
|
||||
if (VSIsWindows11OrGreater()) {
|
||||
msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe";
|
||||
if (cmSystemTools::FileExists(msbuild)) {
|
||||
return msbuild;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe";
|
||||
if (cmSystemTools::FileExists(msbuild)) {
|
||||
return msbuild;
|
||||
}
|
||||
}
|
||||
}
|
||||
msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe";
|
||||
|
Loading…
Reference in New Issue
Block a user