1
0
Эх сурвалжийг харах

Merge topic 'apple-silicon-host-arch' into release-3.19

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 жил өмнө
parent
commit
23df57a3a7

+ 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::
    :maxdepth: 1
 
+   /envvar/CMAKE_APPLE_SILICON_PROCESSOR
    /envvar/CMAKE_BUILD_PARALLEL_LEVEL
    /envvar/CMAKE_CONFIG_TYPE
    /envvar/CMAKE_EXPORT_COMPILE_COMMANDS

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

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

+ 24 - 0
Help/release/3.19.rst

@@ -53,6 +53,22 @@ Languages
 
 * ``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
 --------------
 
@@ -357,3 +373,11 @@ Changes made since CMake 3.19.0 include the following.
   It requires macOS 10.10 or newer.
   The package file naming pattern has been changed from
   ``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.
 
+Windows Platforms
+^^^^^^^^^^^^^^^^^
+
 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
 - on other systems,
 
   * ``uname -p`` if its exit code is nonzero, or
   * ``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()
       exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
     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
         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
             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_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()
-        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()
+      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")
       exec_program(arch ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
         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
    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
   # architecture based on that of the build system tool.
   # 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()
 
 # macOS, iOS, tvOS, and watchOS should lookup compilers from

+ 16 - 0
Tests/CMakeLists.txt

@@ -228,6 +228,22 @@ if(BUILD_TESTING)
     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.
 

+ 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

@@ -176,6 +176,9 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE)
 endif()
 
 add_RunCMake_test(AndroidTestUtilities)
+if(CMake_TEST_APPLE_SILICON)
+  add_RunCMake_test(AppleSilicon)
+endif()
 set(autogen_with_qt5 FALSE)
 if(CMake_TEST_Qt5)
   find_package(Qt5Widgets QUIET NO_MODULE)