diff options
author | Brad King <brad.king@kitware.com> | 2022-07-26 14:27:36 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2022-07-27 11:40:46 (GMT) |
commit | 418fd8556918fa5639d79aca832f0213fb359a02 (patch) | |
tree | 6b296b6ec2ccc44782ab4a979a5fecc328115655 /Source/cmGlobalVisualStudioVersionedGenerator.cxx | |
parent | c508b3625a198cfe4b2f8fbf4acdc2127a28f2cb (diff) | |
download | CMake-418fd8556918fa5639d79aca832f0213fb359a02.zip CMake-418fd8556918fa5639d79aca832f0213fb359a02.tar.gz CMake-418fd8556918fa5639d79aca832f0213fb359a02.tar.bz2 |
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
Diffstat (limited to 'Source/cmGlobalVisualStudioVersionedGenerator.cxx')
-rw-r--r-- | Source/cmGlobalVisualStudioVersionedGenerator.cxx | 126 |
1 files changed, 90 insertions, 36 deletions
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index b72fc4e..7eca963 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -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"; |