macOS: Avoid default -arch flag on Apple Silicon hosts
It should be possible to avoid passing -arch
and -mmacosx-version-min
on Apple platforms.
I maintain libc++, and I need to cross-compile it from macOS to various platforms, both Apple platforms and non-Apple platforms. Following the desire to unify how targets are passed to Clang on Apple platforms and other platforms, I want to use -DCMAKE_CXX_COMPILER_TARGET=x86_64-apple-macosx10.10
for passing the (cross-compilation, backdeployment or else) target to the compiler. However, I am witnessing that CMake will still attempt to guess the -arch
and the -m<platform>-version-min=
flags for me, which leads to problems.
% cmake --version
cmake version 3.25.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
Here's a reproducing script:
#!/usr/bin/env bash
cat <<EOF > CMakeLists.txt
cmake_minimum_required(VERSION 3.19)
project(test CXX)
write_file(main.cpp "int main() { }")
add_executable(main main.cpp)
EOF
rm -rf build && mkdir build
cmake -B build -S . -DCMAKE_CXX_COMPILER_TARGET=x86_64-apple-macosx10.10 -GNinja
ninja -C build -v
In this case, let's say I am trying to compile for a x86_64-apple-macosx10.10
target from a arm64-apple-macosx11.0
build host. Here's what I get:
$ ./repro.sh
-- The CXX compiler identification is AppleClang <...>
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: <...>.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: <...>/repro-cmake/build
ninja: Entering directory `build'
[1/2] <...>.xctoolchain/usr/bin/c++ --target=x86_64-apple-macosx10.10 -arch arm64 -isysroot <SDK> -mmacosx-version-min=11.0 -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c <...>/repro-cmake/main.cpp
clang: warning: overriding '-mmacosx-version-min=11.0' option with '--target=x86_64-apple-macosx10.10' [-Woverriding-t-option]
[2/2] : && <...>.xctoolchain/usr/bin/c++ --target=x86_64-apple-macosx10.10 -arch arm64 -isysroot <SDK> -mmacosx-version-min=11.0 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/main.dir/main.cpp.o -o main && :
clang: warning: overriding '-mmacosx-version-min=11.0' option with '--target=x86_64-apple-macosx10.10' [-Woverriding-t-option]
There are two problematic things here. First, -arch arm64
is passed although I clearly requested a specific --target
. Since -arch
is passed second, it actually ends up overriding the triple passed from the Clang driver to the Clang frontend, as can be seen by adding -###
to the compiler invocation: "-triple" "arm64-apple-macosx10.10.0"
is passed. This results in code compiled for the wrong architecture (!!!).
Second, -mmacosx-version-min=11.0
is passed despite having passed the --target
. This results in the annoying warning, however this is a bit more benign since it is overridden by the specified --target
.
It is also surprising that passing -DCMAKE_OSX_ARCHITECTURES="" -DCMAKE_OSX_DEPLOYMENT_TARGET=""
to the CMake configuration does not disable this behavior, as one might have thought.
There is a very long way to go towards standardizing on using --target
on Apple platforms, however it would be nice if CMake allowed using the CMAKE_<LANG>_COMPILER_TARGET
setting more easily on Apple platforms. I think it might be as simple as disabling any handling of CMAKE_OSX_DEPLOYMENT_TARGET
and CMAKE_OSX_ARCHITECTURES
when CMAKE_<LANG>_COMPILER_TARGET
is specified (in fact using those could be an error).