# How to determine which architectures are available (Apple M1)?

**URL:** https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401
**Category:** Code
**Created:** [December 20, 2020, 7:34pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401 "2020-12-20T19:34:00Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [December 20, 2020, 7:34pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/1 "2020-12-20T19:34:00Z")

</div>

I have 2 different machines: an “old” Intel mac and a new M1 mac.

On the new (M1) mac I can write this to build a universal binary:

```nohighlight
IF(APPLE)
  SET(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "Build architectures for Mac OS X" FORCE)
ENDIF(APPLE)

```

But I cannot do that on an Intel mac (it is running an older version of macOS hence an older version of Xcode which does not support arm64 anyway). Is there a way to get the list of supported architectures by the tool chain?

Thanks

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [December 22, 2020, 4:54pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/2 "2020-12-22T16:54:10Z")

</div>

If I set `CMAKE_OSX_ARCHITECTURES` to `x86_64;arm64` with XCode 11.3.1 (macos 10.14.6) I confirm that it just doesn’t work:

```nohighlight
CMake Error at /Applications/CLion.app/Contents/bin/cmake/mac/share/cmake-3.17/Modules/CMakeTestCCompiler.cmake:60 (message):
  The C compiler

    "/Applications/Xcode11.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: /Volumes/Vault/deployment/build/vst-sam-spl-64/Debug/CMakeFiles/CMakeTmp
    
    Run Build Command(s):/usr/bin/make cmTC_7d8db/fast && /Applications/Xcode11.3.1.app/Contents/Developer/usr/bin/make -f CMakeFiles/cmTC_7d8db.dir/build.make CMakeFiles/cmTC_7d8db.dir/build
    Building C object CMakeFiles/cmTC_7d8db.dir/testCCompiler.c.o
    /Applications/Xcode11.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -arch x86_64 -arch arm64 -isysroot /Applications/Xcode11.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -mmacosx-version-min=10.14 -o CMakeFiles/cmTC_7d8db.dir/testCCompiler.c.o -c /Volumes/Vault/deployment/build/vst-sam-spl-64/Debug/CMakeFiles/CMakeTmp/testCCompiler.c
    Linking C executable cmTC_7d8db
    /Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake -E cmake_link_script CMakeFiles/cmTC_7d8db.dir/link.txt --verbose=1
    /Applications/Xcode11.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -arch x86_64 -arch arm64 -isysroot /Applications/Xcode11.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -mmacosx-version-min=10.14 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/cmTC_7d8db.dir/testCCompiler.c.o -o cmTC_7d8db 
    ld: warning: ignoring file /Applications/Xcode11.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/lib/darwin/libclang_rt.osx.a, missing required architecture arm64 in file /Applications/Xcode11.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.0/lib/darwin/libclang_rt.osx.a (3 slices)
    ld: warning: ignoring file /Applications/Xcode11.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/lib/libSystem.tbd, missing required architecture arm64 in file /Applications/Xcode11.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/lib/libSystem.tbd
    ld: dynamic main executables must link with libSystem.dylib for architecture arm64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    make[1]: *** [cmTC_7d8db] Error 1
    make: *** [cmTC_7d8db/fast] Error 2

```

So any idea of how I can test for architecture support?

Thanks

---

<div class="post-metadata">

### Author: ![smokris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/smokris/32/108_2.png) [@smokris](https://discourse.cmake.org/u/smokris)
#### Post date: [December 22, 2020, 5:31pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/3 "2020-12-22T17:31:48Z")

</div>

> [@fry](#):
>
> how I can test for architecture support

This works for me:

```
cmake_minimum_required(VERSION 3.19)
project(Test)
include(CheckCCompilerFlag)

set(CMAKE_REQUIRED_LINK_OPTIONS "-arch;x86_64")
check_c_compiler_flag("-arch x86_64" x86_64Supported)
message("x86_64Supported=${x86_64Supported}")

set(CMAKE_REQUIRED_LINK_OPTIONS "-arch;arm64")
check_c_compiler_flag("-arch arm64" arm64Supported)
message("arm64Supported=${arm64Supported}")

```

On Xcode 12.3 it indicates both x86\_64 and arm64 are supported; on Xcode 8.2.1 it indicates only x86\_64 is supported.

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [December 22, 2020, 5:59pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/4 "2020-12-22T17:59:59Z")

</div>

I guess it is a chicken and egg problem…

The `CMAKE_OSX_ARCHITECTURES` variable is supposed to be set **before** calling `project` but it looks like `check_c_compiler_flag` needs to be called after project

```auto
CMake Error at /Applications/CLion.app/Contents/bin/cmake/mac/share/cmake-3.17/Modules/CheckCSourceCompiles.cmake:109 (try_compile):
  Unknown extension ".c" for file

    /Volumes/Vault/deployment/build/vst-sam-spl-64/Debug/CMakeFiles/CMakeTmp/src.c

  try_compile() works only for enabled languages. Currently these are:

    

  See project() command to enable other languages.

```

It seems to me that I am going to have to invoke some command line program (like `sysctl -a | grep machdep.cpu.brand_string`) via `execute_process` to determine the processor ☹

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [December 23, 2020, 10:21am UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/5 "2020-12-23T10:21:20Z")

</div>

@fry I’ve posted a related question asking for assistance testing an approach which may help you in producing universal binaries. If you are able to give that test project a go, it would be much appreciated.

> [@Looking for someone willing verify a minimal Xcode project on Apple Silicon](https://discourse.cmake.org/t/looking-for-someone-willing-verify-a-minimal-xcode-project-on-apple-silicon/2415):
>
> I’m trying to verify a minimal combination of settings that will allow an Xcode project to produce a universal binary on macOS. I don’t have access to an Apple Silicon machine, so I can only verify that it works on Intel. Would anyone with access to an Apple Silicon machine be willing to test out the attached project? It is very minimal and has brief instructions in the README file contained therein. Make sure when you run CMake that there isn’t already a previous run in that build directory. [M…](https://discourse.cmake.org/uploads/short-url/insoKhJCmiachi33WoR1lSDNUZi.gz)

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [December 23, 2020, 1:47pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/6 "2020-12-23T13:47:35Z")

</div>

@craig.scott No problem I will try it and report back

---

<div class="post-metadata">

### Author: ![smokris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/smokris/32/108_2.png) [@smokris](https://discourse.cmake.org/u/smokris)
#### Post date: [December 23, 2020, 4:12pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/7 "2020-12-23T16:12:04Z")

</div>

> [@fry](#):
>
> chicken and egg problem

Ah, I see. Yeah, `check_c_compiler_flag` won’t work then.

> [@fry](#):
>
> It seems to me that I am going to have to invoke some command line program (like `sysctl -a | grep machdep.cpu.brand_string`) via execute\_process to determine the processor

(There’s also the `arch` command whose output might be easier to parse.)

One thing to watch out for is that the system CPU architecture doesn’t necessarily match the architectures that Xcode can compile for, since Xcode 12 running on x86\_64 can cross-compile for arm64. I’m not aware of a straightforward way to query which architectures a given `Xcode.app` bundle can cross-compile for, but it’s easy to test:

```
file(WRITE test.c "int main(void) { return 0; }")
execute_process(COMMAND /usr/bin/xcrun clang -arch arm64 test.c ERROR_QUIET RESULT_VARIABLE arm64Error)
if (arm64Error)
    message("cross-compiling for arm64 isn't supported")
else()
    message("cross-compiling for arm64 is supported")
endif()

```

On Xcode 12, the test compile and link both succeed. On earlier Xcode versions, it compiles (since earlier Xcode versions include arm64 support for iOS devices), but linking fails since the macOS `libSystem` doesn’t include an arm64 slice.

(This has the caveat that, if there are multiple toolchains installed on the system, `xcrun`/`xcode-select` might not use the same one that CMake’s `project()`/`enable_language()` will later pick.)

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [December 23, 2020, 7:09pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/8 "2020-12-23T19:09:04Z")

</div>

@smokris Thank you for the help. I agree with you and the caveat.

The command `uname -m` returns the exact architecture of the machine (`x86_64` or `arm64`) but you are correct that it doesn’t say whether the compiler will allow cross compilation.

Since it looks like everybody compiling in the near future for macOS will be faced with the same kind of issue, I am hoping that this can be a part of CMake. Maybe a new variable like `XCODE_UNIVERSAL_BUILD_WHEN_AVAILABLE` which would do the right thing whether on M1 (universal build) or Intel (single build)?

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [December 23, 2020, 10:57pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/9 "2020-12-23T22:57:32Z")

</div>

I don’t think a new variable is needed. It looks like you can set `CMAKE_OSX_ARCHITECTURES` to `$(ARCHS_STANDARD)` if you want a universal build where available for macOS. CMake’s default behavior has always been to build for the native host architecture only. There was a fair amount of investigation and work that went into keeping that behavior with Xcode 12 and Apple Silicon to avoid various problems. See [issue 20893](https://gitlab.kitware.com/cmake/cmake/-/issues/20893) for the fairly detailed discussions and related information.

Depending on what version of macOS and Xcode you are running, you may also need to set `CMAKE_OSX_DEPLOYMENT_TARGET` to be able to run your built apps. I have the situation locally where I build with Xcode 12.3 on an intel running macOS 10.15. If I don’t specify `CMAKE_OSX_DEPLOYMENT_TARGET`, I end up building a valid binary that I can’t run on my machine.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [December 23, 2020, 11:03pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/10 "2020-12-23T23:03:09Z")

</div>

> [@smokris](#):
>
> (This has the caveat that, if there are multiple toolchains installed on the system, `xcrun`/`xcode-select` might not use the same one that CMake’s `project()`/`enable_language()` will later pick.)

I don’t think I’ve seen that myself. When you say “multiple toolchains”, do you mean multiple Xcode versions installed at once, or different SDKs within the one Xcode version? If the latter, do you mean just having different architectures’ SDKs installed? Xcode will usually have the different architectures SDKs, so the latter case is the normal one.

CMake has always picked up the right toolchain for me, and I have multiple Xcode versions installed too. I switch between them either by changing the default one (using `xcode-select` or within the Xcode IDE preferences) or by setting the `DEVELOPER_DIR` environment variable when running CMake for the first time in a build directory.

---

<div class="post-metadata">

### Author: ![smokris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/smokris/32/108_2.png) [@smokris](https://discourse.cmake.org/u/smokris)
#### Post date: [December 24, 2020, 4:09pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/11 "2020-12-24T16:09:34Z")

</div>

> [@craig.scott](#):
>
> When you say “multiple toolchains”, do you mean multiple Xcode versions installed at once, or different SDKs within the one Xcode version?

I was thinking of non-Xcode toolchains (e.g., LLVM/Clang installed via Conan that `xcode-select` doesn’t know about), selected by setting `CMAKE_<LANG>_COMPILER`.

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [January 4, 2021, 2:23pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/12 "2021-01-04T14:23:38Z")

</div>

I wanted to report back on how I ended up implementing it. I am not saying it is the best way or the only way to do it, but it is the way that makes the most sense for my project/framework. I know that a solution proposed in another thread (and in the 8th edition of the book) is to use `$(ARCHS_STANDARD)` which gets expanded by Xcode, but I don’t like it because the content of this variable is not available in CMake so I can’t act on it (printing a message, generating the zip archive name, etc…) (see below).

The full source is available on [github](https://github.com/pongasoft/jamba/blob/v5.1.2/cmake/JambaSetArchitecture.cmake).

The gist of it:

- allow to disable universal build if you don’t want it via an option
- run `uname -m` to determine the platform hence whether universal build is even an option
- check whether the generator is Xcode otherwise you can’t do a universal build
- I also set a variable (`JAMBA_ARCHIVE_ARCHITECTURE`) representing the build architecture so that it is available in other places for example to determine the name of the zip file generated and also injected in a header in the code (#define). This would be impossible to do with `$(ARCHS_STANDARD)`…

````auto
# Enable/Disable universal build on Apple Silicon
option(JAMBA_ENABLE_XCODE_UNIVERSAL_BUILD "Enable building x86/arm64 universal binary on Apple Silicon" ON)

# Deployment target/architectures for macOS
if(APPLE)
  # set the deployment target if provided
  if(JAMBA_MACOS_DEPLOYMENT_TARGET)
    set(CMAKE_OSX_DEPLOYMENT_TARGET "${JAMBA_MACOS_DEPLOYMENT_TARGET}" CACHE STRING "")
  endif()

  # on macOS "uname -m" returns the architecture (x86_64 or arm64)
  execute_process(
      COMMAND uname -m
      RESULT_VARIABLE result
      OUTPUT_VARIABLE JAMBA_OSX_NATIVE_ARCHITECTURE
      OUTPUT_STRIP_TRAILING_WHITESPACE
  )

  # determine if we do universal build or native build
  if(JAMBA_ENABLE_XCODE_UNIVERSAL_BUILD # is universal build enabled?
      AND (CMAKE_GENERATOR STREQUAL "Xcode") # works only with Xcode
      AND (JAMBA_OSX_NATIVE_ARCHITECTURE STREQUAL "arm64")) # and only when running on arm64
    set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "")
    set(JAMBA_ARCHIVE_ARCHITECTURE "macOS_universal")
    message(STATUS "macOS universal (x86_64 / arm64) build")
  else()
    set(JAMBA_ARCHIVE_ARCHITECTURE "macOS_${JAMBA_OSX_NATIVE_ARCHITECTURE}")
    message(STATUS "macOS native ${JAMBA_OSX_NATIVE_ARCHITECTURE} build")
  endif()

elseif(WIN32)
  # nothing special for windows
  set(JAMBA_ARCHIVE_ARCHITECTURE "win_64bits")
  message(STATUS "Windows native build")
endif()```
````

---

<div class="post-metadata">

### Author: ![wildkid.long](https://discourse.cmake.org/user_avatar/discourse.cmake.org/wildkid.long/32/3156_2.png) [@wildkid.long](https://discourse.cmake.org/u/wildkid.long)
#### Post date: [February 10, 2023, 5:53am UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/13 "2023-02-10T05:53:37Z")

</div>

I simplified your answer and hope you like it.

if(APPLE)  
execute\_process(COMMAND uname -m  
OUTPUT\_VARIABLE CMAKE\_OSX\_ARCHITECTURES  
OUTPUT\_STRIP\_TRAILING\_WHITESPACE)  
endif(APPLE)

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [February 10, 2023, 1:39pm UTC](https://discourse.cmake.org/t/how-to-determine-which-architectures-are-available-apple-m1/2401/14 "2023-02-10T13:39:22Z")

</div>

Except that your answer is wrong. If you look at what I am actually doing, I am building a universal application.

`uname -m` only returns `arm64` on an M1 so setting `CMAKE_OSX_ARCHITECTURES` to the result of `uname -m` will build an M1 only application.

This is why I am using `set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "")`. But on top of that, it only works if the generator is Xcode.

So no, your “simplification” does **NOT** do what my code does and is certainly **NOT** setting `CMAKE_OSX_ARCHITECTURES` to `x86_64;arm64` as the original question was asking…
