Quellcode durchsuchen

FindPython: Add Windows/ARM support

Fixes: #24587
Marc Chevrier vor 2 Jahren
Ursprung
Commit
9913c28ebb
2 geänderte Dateien mit 89 neuen und 26 gelöschten Zeilen
  1. 5 0
      Help/release/dev/FindPython-Windows-ARM.rst
  2. 84 26
      Modules/FindPython/Support.cmake

+ 5 - 0
Help/release/dev/FindPython-Windows-ARM.rst

@@ -0,0 +1,5 @@
+FindPython-Windows-ARM
+----------------------
+
+* :module:`FindPython`, :module:`FindPython2` and :module:`FindPython3` modules
+  learn to manage ``Windows/ARM`` platform.

+ 84 - 26
Modules/FindPython/Support.cmake

@@ -192,28 +192,25 @@ function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS)
     if (implementation STREQUAL "CPython")
       foreach (version IN LISTS _PGR_VERSION)
         string (REPLACE "." "" version_no_dots ${version})
-        list (APPEND registries
-                     [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
-                     [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath])
+        list (TRANSFORM _${_PYTHON_PREFIX}_ARCH REPLACE "^(.+)$" "[HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-\\1/InstallPath]" OUTPUT_VARIABLE reg_paths)
+        list (APPEND registries ${reg_paths})
         if (version VERSION_GREATER_EQUAL "3.5")
           # cmake_host_system_information is not usable in bootstrap
           get_filename_component (arch "[HKEY_CURRENT_USER\\Software\\Python\\PythonCore\\${version};SysArchitecture]" NAME)
-          if (arch MATCHES "(${_${_PYTHON_PREFIX}_ARCH}|${_${_PYTHON_PREFIX}_ARCH2})bit")
-            list (APPEND registries
-                         [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath])
+          string (REPLACE "bit" "" arch "${arch}")
+          if (arch IN_LIST _${_PYTHON_PREFIX}_ARCH)
+            list (APPEND registries [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath])
           endif()
         else()
-          list (APPEND registries
-                       [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath])
-        endif()
-        list (APPEND registries
-                     [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
-                     [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]
-                     [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
-                     [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]
-                     [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}/InstallPath]
-                     [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
-                     [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath])
+          list (APPEND registries [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath])
+        endif()
+        list (TRANSFORM _${_PYTHON_PREFIX}_ARCH REPLACE "^(.+)$" "[HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-\\1/InstallPath]" OUTPUT_VARIABLE reg_paths)
+        list (APPEND registries ${reg_paths})
+        list (TRANSFORM _${_PYTHON_PREFIX}_ARCH REPLACE "^(.+)$" "[HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-\\1/InstallPath]" OUTPUT_VARIABLE reg_paths)
+        list (APPEND registries ${reg_paths})
+        list (APPEND registries [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}/InstallPath])
+        list (TRANSFORM _${_PYTHON_PREFIX}_ARCH REPLACE "^(.+)$" "[HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-\\1/InstallPath]" OUTPUT_VARIABLE reg_paths)
+        list (APPEND registries ${reg_paths})
       endforeach()
     elseif (implementation STREQUAL "IronPython")
       foreach (version  IN LISTS _PGR_VERSION)
@@ -927,6 +924,33 @@ function (_PYTHON_VALIDATE_INTERPRETER)
       set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
       return()
     endif()
+
+    if (WIN32)
+      # In this case, check if the interpreter is compatible with the target processor architecture
+      if (NOT CMAKE_GENERATOR_PLATFORM AND CMAKE_SYSTEM_PROCESSOR MATCHES "ARM" OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM")
+        set(target_arm TRUE)
+      else()
+        set(target_arm FALSE)
+      endif()
+      execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
+        "import sys, sysconfig; sys.stdout.write(sysconfig.get_platform())"
+        RESULT_VARIABLE result
+        OUTPUT_VARIABLE platform
+        ERROR_QUIET
+        OUTPUT_STRIP_TRAILING_WHITESPACE)
+      string(TOUPPER "${platform}" platform)
+      if (result OR ((target_arm AND NOT platform MATCHES "ARM") OR
+                     (NOT target_arm AND platform MATCHES "ARM")))
+        # interpreter not usable or has wrong architecture
+        if (result)
+          set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
+        else()
+          set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
+        endif()
+        set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
+        return()
+      endif()
+    endif()
   endif()
 endfunction()
 
@@ -1419,19 +1443,37 @@ if (CMAKE_SIZEOF_VOID_P)
       OR "Development.SABIModule" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
       OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
     # In this case, search only for 64bit or 32bit
-    set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
     set (_${_PYTHON_PREFIX}_REGISTRY_VIEW REGISTRY_VIEW ${_${_PYTHON_PREFIX}_ARCH})
+    if (WIN32 AND (NOT CMAKE_GENERATOR_PLATFORM AND CMAKE_SYSTEM_PROCESSOR MATCHES "ARM"
+                   OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM"))
+      # search exclusively ARM architecture: 64bit or 32bit
+      if (_${_PYTHON_PREFIX}_ARCH EQUAL 64)
+        set (_${_PYTHON_PREFIX}_ARCH ARM64)
+      else()
+        set (_${_PYTHON_PREFIX}_ARCH ARM)
+      endif()
+    endif()
   else()
     if (_${_PYTHON_PREFIX}_ARCH EQUAL "32")
-      set (_${_PYTHON_PREFIX}_ARCH2 64)
+      if (CMAKE_SYSTEM_PROCESSOR MATCHES "ARM")
+        # search first ARM architectures: 32bit and then 64bit
+        list (PREPEND _${_PYTHON_PREFIX}_ARCH ARM ARM64)
+      endif()
+      list (APPEND _${_PYTHON_PREFIX}_ARCH 64)
     else()
-      set (_${_PYTHON_PREFIX}_ARCH2 32)
+      if (CMAKE_SYSTEM_PROCESSOR MATCHES "ARM")
+        # search first ARM architectures: 64bit and then 32bit
+        list (PREPEND _${_PYTHON_PREFIX}_ARCH ARM64 ARM)
+      endif()
+      list (APPEND _${_PYTHON_PREFIX}_ARCH 32)
     endif()
   endif()
 else()
   # architecture unknown, search for both 64bit and 32bit
-  set (_${_PYTHON_PREFIX}_ARCH 64)
-  set (_${_PYTHON_PREFIX}_ARCH2 32)
+  set (_${_PYTHON_PREFIX}_ARCH 64 32)
+  if (CMAKE_SYSTEM_PROCESSOR MATCHES "ARM")
+    list (PREPEND _${_PYTHON_PREFIX}_ARCH ARM64 ARM)
+  endif()
 endif()
 
 # IronPython support
@@ -1439,7 +1481,7 @@ unset (_${_PYTHON_PREFIX}_IRON_PYTHON_INTERPRETER_NAMES)
 unset (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_NAMES)
 unset (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS)
 if (CMAKE_SIZEOF_VOID_P)
-  if (_${_PYTHON_PREFIX}_ARCH EQUAL "32")
+  if (CMAKE_SIZEOF_VOID_P EQUAL "4")
     set (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS "/platform:x86")
   else()
     set (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS "/platform:x64")
@@ -2048,7 +2090,6 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
       list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 3 ${_PYTHON_PREFIX}_VERSION_PATCH)
 
       list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 4 _${_PYTHON_PREFIX}_ARCH)
-      set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
 
       list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 5 _${_PYTHON_PREFIX}_ABIFLAGS)
       list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 6 ${_PYTHON_PREFIX}_SOABI)
@@ -2098,10 +2139,27 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
           if (NOT _${_PYTHON_PREFIX}_RESULT)
             if (${_PYTHON_PREFIX}_IS64BIT)
               set (_${_PYTHON_PREFIX}_ARCH 64)
-              set (_${_PYTHON_PREFIX}_ARCH2 64)
             else()
               set (_${_PYTHON_PREFIX}_ARCH 32)
-              set (_${_PYTHON_PREFIX}_ARCH2 32)
+            endif()
+          endif()
+
+          if (WIN32)
+            # check if architecture is Intel or ARM
+            execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
+                                     "import sys; import sysconfig; sys.stdout.write(sysconfig.get_platform())"
+                             RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                             OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PLATFORM
+                             ERROR_VARIABLE ${_PYTHON_PREFIX}_PLATFORM)
+            if (NOT _${_PYTHON_PREFIX}_RESULT)
+              string(TOUPPER "${_${_PYTHON_PREFIX}_PLATFORM}" _${_PYTHON_PREFIX}_PLATFORM)
+              if (_${_PYTHON_PREFIX}_PLATFORM MATCHES "ARM")
+                if (${_PYTHON_PREFIX}_IS64BIT)
+                  set (_${_PYTHON_PREFIX}_ARCH ARM64)
+                else()
+                  set (_${_PYTHON_PREFIX}_ARCH ARM)
+                endif()
+              endif()
             endif()
           endif()
         endif()