CMake's default `CMAKE_CXX_COMPILER` on Apple platforms shouldn't be resolved from `xcrun --find`
On Apple platforms, CMake resolves the default C++ compiler to the executable given by xcrun --find c++
instead of using something like /usr/bin/c++
. The compiler given by xcrun --find c++
is an executable inside the Xcode toolchain (something like <path>/Xcode.app/Contents/Developer/Toolchains/<toolchain>/usr/bin/c++)
. However, on Apple platforms, it is unusual to call that executable directly. Usually, the compiler is called through shims present in /usr/bin
, which set up important information for the compiler, such as the path to the SDK (with the SDKROOT
environment variable).
That causes the default CMAKE_CXX_COMPILER
to not work out-of-the-box if used naively, because when invoking $(xcrun --find c++)
directly, the SDKROOT
isn't set and the compiler doesn't know where to get the C Standard Library headers from. Here's a self-contained reproducer where we basically configure a script that tries to use the CMAKE_CXX_COMPILER
to compile a simple file, which fails:
rm -rf test-cmake && mkdir -p test-cmake/build
cat <<EOF > test-cmake/some-script.sh.in
echo "#include <vector>" | @CMAKE_CXX_COMPILER@ -xc++ - -fsyntax-only
EOF
cat <<EOF > test-cmake/CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(test CXX)
configure_file(some-script.sh.in some-script.sh)
EOF
cmake -S test-cmake -B test-cmake/build
bash test-cmake/build/some-script.sh
The result is:
In file included from <stdin>:1:
In file included from <toolchain>/usr/bin/../include/c++/v1/vector:275:
In file included from <toolchain>/usr/bin/../include/c++/v1/iosfwd:95:
<toolchain>/usr/bin/../include/c++/v1/wchar.h:119:15: fatal error: 'wchar.h' file not found
#include_next <wchar.h>
^~~~~~~~~
1 error generated.
Note that using cmake -S test-cmake -B test-cmake/build -DCMAKE_CXX_COMPILER=c++
in the script above fixes the issue, but it seems like it should work out of the box (and both should be equivalent).
Is this by design? This report was simplified from a real use case where we try to use the @CMAKE_CXX_COMPILER@
to run the tests for Apple's own C++ Standard Library. In my opinion, it would make more sense if the compiler detected by default was simply /usr/bin/c++
, which will then handle the xcrun
business for us under the hood.