Răsfoiți Sursa

Merge topic 'apple-silicon-host-arch'

b7f0327dcd Tests: Cover macOS host architecture selection on Apple Silicon hosts
5f882f6ce5 macOS: Offer control over host architecture on Apple Silicon hosts

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5589
Brad King 4 ani în urmă
părinte
comite
794aa36b1f

+ 13 - 0
Help/envvar/CMAKE_APPLE_SILICON_PROCESSOR.rst

@@ -0,0 +1,13 @@
+CMAKE_APPLE_SILICON_PROCESSOR
+-----------------------------
+
+.. versionadded:: 3.19.2
+
+.. include:: ENV_VAR.txt
+
+On Apple Silicon hosts running macOS, set this environment variable to tell
+CMake what architecture to use for :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`.
+The value must be either ``arm64`` or ``x86_64``.
+
+The :variable:`CMAKE_APPLE_SILICON_PROCESSOR` normal variable, if set,
+overrides this environment variable.

+ 1 - 0
Help/manual/cmake-env-variables.7.rst

@@ -28,6 +28,7 @@ Environment Variables that Control the Build
 .. toctree::
 .. toctree::
    :maxdepth: 1
    :maxdepth: 1
 
 
+   /envvar/CMAKE_APPLE_SILICON_PROCESSOR
    /envvar/CMAKE_BUILD_PARALLEL_LEVEL
    /envvar/CMAKE_BUILD_PARALLEL_LEVEL
    /envvar/CMAKE_CONFIG_TYPE
    /envvar/CMAKE_CONFIG_TYPE
    /envvar/CMAKE_EXPORT_COMPILE_COMMANDS
    /envvar/CMAKE_EXPORT_COMPILE_COMMANDS

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -355,6 +355,7 @@ Variables that Control the Build
    /variable/CMAKE_ANDROID_SKIP_ANT_STEP
    /variable/CMAKE_ANDROID_SKIP_ANT_STEP
    /variable/CMAKE_ANDROID_STANDALONE_TOOLCHAIN
    /variable/CMAKE_ANDROID_STANDALONE_TOOLCHAIN
    /variable/CMAKE_ANDROID_STL_TYPE
    /variable/CMAKE_ANDROID_STL_TYPE
+   /variable/CMAKE_APPLE_SILICON_PROCESSOR
    /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG
    /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG
    /variable/CMAKE_AUTOGEN_ORIGIN_DEPENDS
    /variable/CMAKE_AUTOGEN_ORIGIN_DEPENDS

+ 24 - 0
Help/release/3.19.rst

@@ -53,6 +53,22 @@ Languages
 
 
 * ``CUDA`` language support now works on QNX.
 * ``CUDA`` language support now works on QNX.
 
 
+Platforms
+---------
+
+* Apple Silicon is now supported (since CMake 3.19.2):
+
+  * The :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` is selected using ``uname -m``.
+    Since this may vary based on CMake's own architecture and that of
+    the invoking process tree, the :variable:`CMAKE_APPLE_SILICON_PROCESSOR`
+    variable or :envvar:`CMAKE_APPLE_SILICON_PROCESSOR` environment
+    variable may be set to specify a host architecture explicitly.
+
+  * If :variable:`CMAKE_OSX_ARCHITECTURES` is not set, CMake adds explicit
+    flags to tell the compiler to build for the
+    :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` so the toolchain does not
+    have to guess based on the process tree's architecture.
+
 File-Based API
 File-Based API
 --------------
 --------------
 
 
@@ -357,3 +373,11 @@ Changes made since CMake 3.19.0 include the following.
   It requires macOS 10.10 or newer.
   It requires macOS 10.10 or newer.
   The package file naming pattern has been changed from
   The package file naming pattern has been changed from
   ``cmake-$ver-Darwin-x86_64`` to ``cmake-$ver-macos-universal``.
   ``cmake-$ver-Darwin-x86_64`` to ``cmake-$ver-macos-universal``.
+
+* Apple Silicon host architecture selection support was updated.
+  CMake 3.19.0 and 3.19.1 always chose ``arm64`` as the host architecture.
+  CMake 3.19.2 returns to using ``uname -m`` as CMake 3.18 and below did.
+  Since this may vary based on CMake's own architecture and that of
+  the invoking process tree, the :variable:`CMAKE_APPLE_SILICON_PROCESSOR`
+  variable or :envvar:`CMAKE_APPLE_SILICON_PROCESSOR` environment
+  variable may be set to specify a host architecture explicitly.

+ 15 - 0
Help/variable/CMAKE_APPLE_SILICON_PROCESSOR.rst

@@ -0,0 +1,15 @@
+CMAKE_APPLE_SILICON_PROCESSOR
+-----------------------------
+
+.. versionadded:: 3.19.2
+
+On Apple Silicon hosts running macOS, set this variable to tell
+CMake what architecture to use for :variable:`CMAKE_HOST_SYSTEM_PROCESSOR`.
+The value must be either ``arm64`` or ``x86_64``.
+
+The value of this variable should never be modified by project code.
+It is meant to be set by a toolchain file specified by the
+:variable:`CMAKE_TOOLCHAIN_FILE` variable, or as a cache entry
+provided by the user, e.g. via ``-DCMAKE_APPLE_SILICON_PROCESSOR=...``.
+
+See also the :envvar:`CMAKE_APPLE_SILICON_PROCESSOR` environment variable.

+ 30 - 3
Help/variable/CMAKE_HOST_SYSTEM_PROCESSOR.rst

@@ -3,13 +3,40 @@ CMAKE_HOST_SYSTEM_PROCESSOR
 
 
 The name of the CPU CMake is running on.
 The name of the CPU CMake is running on.
 
 
+Windows Platforms
+^^^^^^^^^^^^^^^^^
+
 On Windows, this variable is set to the value of the environment variable
 On Windows, this variable is set to the value of the environment variable
-``PROCESSOR_ARCHITECTURE``. On systems that support ``uname``, this variable is
-set to the output of:
+``PROCESSOR_ARCHITECTURE``.
+
+Unix Platforms
+^^^^^^^^^^^^^^
+
+On systems that support ``uname``, this variable is set to the output of:
 
 
-- ``uname -m`` on GNU, Linux, Cygwin, Darwin, Android, or
+- ``uname -m`` on GNU, Linux, Cygwin, Android, or
 - ``arch`` on OpenBSD, or
 - ``arch`` on OpenBSD, or
 - on other systems,
 - on other systems,
 
 
   * ``uname -p`` if its exit code is nonzero, or
   * ``uname -p`` if its exit code is nonzero, or
   * ``uname -m`` otherwise.
   * ``uname -m`` otherwise.
+
+macOS Platforms
+^^^^^^^^^^^^^^^
+
+The value of ``uname -m`` is used by default.
+
+On Apple Silicon hosts, the architecture printed by ``uname -m`` may vary
+based on CMake's own architecture and that of the invoking process tree.
+
+.. versionadded:: 3.19.2
+
+  On Apple Silicon hosts:
+
+  * The :variable:`CMAKE_APPLE_SILICON_PROCESSOR` variable or
+    the :envvar:`CMAKE_APPLE_SILICON_PROCESSOR` environment variable
+    may be set to specify the host architecture explicitly.
+
+  * If :variable:`CMAKE_OSX_ARCHITECTURES` is not set, CMake adds explicit
+    flags to tell the compiler to build for the host architecture so the
+    toolchain does not have to guess based on the process tree's architecture.

+ 28 - 9
Modules/CMakeDetermineSystem.cmake

@@ -43,25 +43,44 @@ if(CMAKE_HOST_UNIX)
     else()
     else()
       exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
       exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
     endif()
     endif()
-    if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|Darwin|^GNU$|Android")
+    if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|^GNU$|Android")
       exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
       exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
         RETURN_VALUE val)
         RETURN_VALUE val)
-      if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
-        if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
-          # Check whether we are running under Rosetta on arm64 hardware.
+    elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
+      # If we are running on Apple Silicon, honor CMAKE_APPLE_SILICON_PROCESSOR.
+      if(DEFINED CMAKE_APPLE_SILICON_PROCESSOR)
+        set(_CMAKE_APPLE_SILICON_PROCESSOR "${CMAKE_APPLE_SILICON_PROCESSOR}")
+      elseif(DEFINED ENV{CMAKE_APPLE_SILICON_PROCESSOR})
+        set(_CMAKE_APPLE_SILICON_PROCESSOR "$ENV{CMAKE_APPLE_SILICON_PROCESSOR}")
+      else()
+        set(_CMAKE_APPLE_SILICON_PROCESSOR "")
+      endif()
+      if(_CMAKE_APPLE_SILICON_PROCESSOR)
+        if(";${_CMAKE_APPLE_SILICON_PROCESSOR};" MATCHES "^;(arm64|x86_64);$")
           execute_process(COMMAND sysctl -q hw.optional.arm64
           execute_process(COMMAND sysctl -q hw.optional.arm64
             OUTPUT_VARIABLE _sysctl_stdout
             OUTPUT_VARIABLE _sysctl_stdout
             ERROR_VARIABLE _sysctl_stderr
             ERROR_VARIABLE _sysctl_stderr
             RESULT_VARIABLE _sysctl_result
             RESULT_VARIABLE _sysctl_result
             )
             )
-          if(_sysctl_result EQUAL 0 AND _sysctl_stdout MATCHES "hw.optional.arm64: 1")
-            set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64")
+          if(NOT _sysctl_result EQUAL 0 OR NOT _sysctl_stdout MATCHES "hw.optional.arm64: 1")
+            set(_CMAKE_APPLE_SILICON_PROCESSOR "")
           endif()
           endif()
-        elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "Power Macintosh")
-          # OS X ppc 'uname -m' may report 'Power Macintosh' instead of 'powerpc'
-          set(CMAKE_HOST_SYSTEM_PROCESSOR "powerpc")
+          unset(_sysctl_result)
+          unset(_sysctl_stderr)
+          unset(_sysctl_stdout)
         endif()
         endif()
       endif()
       endif()
+      if(_CMAKE_APPLE_SILICON_PROCESSOR)
+        set(CMAKE_HOST_SYSTEM_PROCESSOR "${_CMAKE_APPLE_SILICON_PROCESSOR}")
+      else()
+        exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
+          RETURN_VALUE val)
+      endif()
+      unset(_CMAKE_APPLE_SILICON_PROCESSOR)
+      if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "Power Macintosh")
+        # OS X ppc 'uname -m' may report 'Power Macintosh' instead of 'powerpc'
+        set(CMAKE_HOST_SYSTEM_PROCESSOR "powerpc")
+      endif()
     elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "OpenBSD")
     elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "OpenBSD")
       exec_program(arch ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
       exec_program(arch ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
         RETURN_VALUE val)
         RETURN_VALUE val)

+ 13 - 4
Modules/Platform/Darwin-Initialize.cmake

@@ -22,13 +22,22 @@ set(CMAKE_OSX_ARCHITECTURES "$ENV{CMAKE_OSX_ARCHITECTURES}" CACHE STRING
 
 
 if(NOT CMAKE_CROSSCOMPILING AND
 if(NOT CMAKE_CROSSCOMPILING AND
    CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND
    CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND
-   CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64" AND
-   CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
-  # When building on Apple Silicon (arm64), we need to explicitly specify
+   CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(arm64|x86_64)$")
+  execute_process(COMMAND sysctl -q hw.optional.arm64
+    OUTPUT_VARIABLE _sysctl_stdout
+    ERROR_VARIABLE _sysctl_stderr
+    RESULT_VARIABLE _sysctl_result
+    )
+  # When building on an Apple Silicon host, we need to explicitly specify
   # the architecture to the toolchain since it will otherwise guess the
   # the architecture to the toolchain since it will otherwise guess the
   # architecture based on that of the build system tool.
   # architecture based on that of the build system tool.
   # Set an *internal variable* to tell the generators to do this.
   # Set an *internal variable* to tell the generators to do this.
-  set(_CMAKE_APPLE_ARCHS_DEFAULT "arm64")
+  if(_sysctl_result EQUAL 0 AND _sysctl_stdout MATCHES "hw.optional.arm64: 1")
+    set(_CMAKE_APPLE_ARCHS_DEFAULT "${CMAKE_HOST_SYSTEM_PROCESSOR}")
+  endif()
+  unset(_sysctl_result)
+  unset(_sysctl_stderr)
+  unset(_sysctl_stdout)
 endif()
 endif()
 
 
 # macOS, iOS, tvOS, and watchOS should lookup compilers from
 # macOS, iOS, tvOS, and watchOS should lookup compilers from

+ 16 - 0
Tests/CMakeLists.txt

@@ -228,6 +228,22 @@ if(BUILD_TESTING)
     endif()
     endif()
   endif()
   endif()
 
 
+  if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT DEFINED CMake_TEST_APPLE_SILICON)
+    execute_process(COMMAND sysctl -q hw.optional.arm64
+      OUTPUT_VARIABLE _sysctl_stdout
+      ERROR_VARIABLE  _sysctl_stderr
+      RESULT_VARIABLE _sysctl_result
+      )
+    if(_sysctl_result EQUAL 0 AND _sysctl_stdout MATCHES "hw.optional.arm64: 1")
+      set(CMake_TEST_APPLE_SILICON 1)
+    else()
+      set(CMake_TEST_APPLE_SILICON 0)
+    endif()
+    unset(_sysctl_result)
+    unset(_sysctl_stderr)
+    unset(_sysctl_stdout)
+  endif()
+
   #---------------------------------------------------------------------------
   #---------------------------------------------------------------------------
   # Add tests below here.
   # Add tests below here.
 
 

+ 3 - 0
Tests/RunCMake/AppleSilicon/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.19)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)

+ 27 - 0
Tests/RunCMake/AppleSilicon/RunCMakeTest.cmake

@@ -0,0 +1,27 @@
+include(RunCMake)
+
+# Isolate from caller's environment.
+set(ENV{CMAKE_APPLE_SILICON_PROCESSOR} "")
+set(ENV{CMAKE_OSX_ARCHITECTURES} "")
+
+function(run_arch case)
+  set(RunCMake_TEST_OPTIONS ${ARGN})
+  set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${case}-build")
+  run_cmake(${case})
+  unset(RunCMake_TEST_OPTIONS)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug)
+endfunction()
+
+run_arch(default)
+
+run_arch(arm64-var -DCMAKE_APPLE_SILICON_PROCESSOR=arm64)
+run_arch(x86_64-var -DCMAKE_APPLE_SILICON_PROCESSOR=x86_64)
+
+set(ENV{CMAKE_APPLE_SILICON_PROCESSOR} "arm64")
+run_arch(arm64-env)
+
+set(ENV{CMAKE_APPLE_SILICON_PROCESSOR} "x86_64")
+run_arch(x86_64-env)
+
+set(ENV{CMAKE_APPLE_SILICON_PROCESSOR} "")

+ 10 - 0
Tests/RunCMake/AppleSilicon/arm64-common.cmake

@@ -0,0 +1,10 @@
+enable_language(C)
+
+if(NOT CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
+  message(FATAL_ERROR "CMAKE_HOST_SYSTEM_PROCESSOR is '${CMAKE_HOST_SYSTEM_PROCESSOR}', not 'arm64'")
+endif()
+if(NOT CMAKE_OSX_ARCHITECTURES STREQUAL "")
+  message(FATAL_ERROR "CMAKE_OSX_ARCHITECTURES is '${CMAKE_OSX_ARCHITECTURES}', not empty ''")
+endif()
+
+add_library(arm64 arm64.c)

+ 1 - 0
Tests/RunCMake/AppleSilicon/arm64-env.cmake

@@ -0,0 +1 @@
+include(arm64-common.cmake)

+ 1 - 0
Tests/RunCMake/AppleSilicon/arm64-var.cmake

@@ -0,0 +1 @@
+include(arm64-common.cmake)

+ 9 - 0
Tests/RunCMake/AppleSilicon/arm64.c

@@ -0,0 +1,9 @@
+#ifndef __aarch64__
+#  error "Not compiling as arm64"
+#endif
+#ifdef __x86_64__
+#  error "Incorrectly compiling as x86_64"
+#endif
+void arm64_arch(void)
+{
+}

+ 14 - 0
Tests/RunCMake/AppleSilicon/default.c

@@ -0,0 +1,14 @@
+#if defined(HOST_ARM64)
+#  if !defined(__aarch64__)
+#    error "Not compiling as host arm64"
+#  endif
+#elif defined(HOST_X86_64)
+#  if !defined(__x86_64__)
+#    error "Not compiling as host x86_64"
+#  endif
+#else
+#  error "One of HOST_ARM64 or HOST_X86_64 must be defined."
+#endif
+void default_arch(void)
+{
+}

+ 15 - 0
Tests/RunCMake/AppleSilicon/default.cmake

@@ -0,0 +1,15 @@
+enable_language(C)
+
+if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
+  set(host_def HOST_ARM64)
+elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
+  set(host_def HOST_X86_64)
+else()
+  message(FATAL_ERROR "CMAKE_HOST_SYSTEM_PROCESSOR is '${CMAKE_HOST_SYSTEM_PROCESSOR}', not 'arm64' or 'x86_64'")
+endif()
+if(NOT CMAKE_OSX_ARCHITECTURES STREQUAL "")
+  message(FATAL_ERROR "CMAKE_OSX_ARCHITECTURES is '${CMAKE_OSX_ARCHITECTURES}', not empty ''")
+endif()
+
+add_library(default default.c)
+target_compile_definitions(default PRIVATE ${host_def})

+ 10 - 0
Tests/RunCMake/AppleSilicon/x86_64-common.cmake

@@ -0,0 +1,10 @@
+enable_language(C)
+
+if(NOT CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
+  message(FATAL_ERROR "CMAKE_HOST_SYSTEM_PROCESSOR is '${CMAKE_HOST_SYSTEM_PROCESSOR}', not 'x86_64'")
+endif()
+if(NOT CMAKE_OSX_ARCHITECTURES STREQUAL "")
+  message(FATAL_ERROR "CMAKE_OSX_ARCHITECTURES is '${CMAKE_OSX_ARCHITECTURES}', not empty ''")
+endif()
+
+add_library(x86_64 x86_64.c)

+ 1 - 0
Tests/RunCMake/AppleSilicon/x86_64-env.cmake

@@ -0,0 +1 @@
+include(x86_64-common.cmake)

+ 1 - 0
Tests/RunCMake/AppleSilicon/x86_64-var.cmake

@@ -0,0 +1 @@
+include(x86_64-common.cmake)

+ 9 - 0
Tests/RunCMake/AppleSilicon/x86_64.c

@@ -0,0 +1,9 @@
+#ifndef __x86_64__
+#  error "Not compiling as x86_64"
+#endif
+#ifdef __aarch64__
+#  error "Incorrectly compiling as arm64"
+#endif
+void x86_64_arch(void)
+{
+}

+ 3 - 0
Tests/RunCMake/CMakeLists.txt

@@ -186,6 +186,9 @@ set_property(TEST RunCMake.ABI APPEND
   PROPERTY LABELS "CUDA")
   PROPERTY LABELS "CUDA")
 
 
 add_RunCMake_test(AndroidTestUtilities)
 add_RunCMake_test(AndroidTestUtilities)
+if(CMake_TEST_APPLE_SILICON)
+  add_RunCMake_test(AppleSilicon)
+endif()
 set(autogen_with_qt5 FALSE)
 set(autogen_with_qt5 FALSE)
 if(CMake_TEST_Qt5)
 if(CMake_TEST_Qt5)
   find_package(Qt5Widgets QUIET NO_MODULE)
   find_package(Qt5Widgets QUIET NO_MODULE)