Browse Source

macOS: Default to arm64 architecture on Apple Silicon hosts

Detect `arm64` hardware using a method that pierces Rosetta.  If
`CMAKE_OSX_ARCHITECTURES` is not set, pass explicit flags to the
toolchain to use `arm64` instead of letting the toolchain pick.

Fixes: #20989
Brad King 5 years ago
parent
commit
b6c60f14b6

+ 15 - 4
Modules/CMakeDetermineSystem.cmake

@@ -46,10 +46,21 @@ if(CMAKE_HOST_UNIX)
     if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|Darwin|^GNU$|Android")
       exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR
         RETURN_VALUE val)
-      if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND
-         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")
+      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.
+          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")
+          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")
+        endif()
       endif()
     elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "OpenBSD")
       exec_program(arch ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR

+ 11 - 0
Modules/Platform/Darwin-Initialize.cmake

@@ -20,6 +20,17 @@ execute_process(COMMAND sw_vers -productVersion
 set(CMAKE_OSX_ARCHITECTURES "$ENV{CMAKE_OSX_ARCHITECTURES}" CACHE STRING
   "Build architectures for OSX")
 
+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
+  # 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")
+endif()
+
 # macOS, iOS, tvOS, and watchOS should lookup compilers from
 # Platform/Apple-${CMAKE_CXX_COMPILER_ID}-<LANG>
 set(CMAKE_EFFECTIVE_SYSTEM_NAME "Apple")

+ 3 - 0
Source/cmGeneratorTarget.cxx

@@ -3193,6 +3193,9 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
   if (archs) {
     cmExpandList(*archs, archVec);
   }
+  if (archVec.empty()) {
+    this->Makefile->GetDefExpandList("_CMAKE_APPLE_ARCHS_DEFAULT", archVec);
+  }
 }
 
 void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const

+ 4 - 0
Source/cmGlobalXCodeGenerator.cxx

@@ -4023,6 +4023,10 @@ void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf)
     mf->GetDefExpandList("CMAKE_OSX_ARCHITECTURES", this->Architectures);
   }
 
+  if (this->Architectures.empty()) {
+    mf->GetDefExpandList("_CMAKE_APPLE_ARCHS_DEFAULT", this->Architectures);
+  }
+
   if (this->Architectures.empty()) {
     // With no ARCHS we use ONLY_ACTIVE_ARCH and possibly a
     // platform-specific default ARCHS placeholder value.

+ 2 - 0
Tests/Assembler/CMakeLists.txt

@@ -18,6 +18,8 @@ if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode|Ninja" AND
     endif()
     if(CMAKE_OSX_ARCHITECTURES)
       list(APPEND C_FLAGS -arch ${CMAKE_OSX_ARCHITECTURES})
+    elseif("${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Darwin;arm64")
+      list(APPEND C_FLAGS -arch arm64)
     endif()
     # Clang on OS X, and perhaps other compilers, do not support -g
     # for both generating and assembling, so drop it from generating.