Browse Source

Merge topic 'vs-msbuild-arm64' into release-3.24

418fd85569 VS: Detect ARM64 host architecture at runtime

Acked-by: Kitware Robot <[email protected]>
Acked-by: Tommy Vercetti <[email protected]>
Acked-by: Anton Lapounov <[email protected]>
Merge-request: !7511
Brad King 3 years ago
parent
commit
859f50a4ed
1 changed files with 90 additions and 36 deletions
  1. 90 36
      Source/cmGlobalVisualStudioVersionedGenerator.cxx

+ 90 - 36
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";