3

On my Apple M2 (ARM64-apple-darwin) I have the following C++ code stored in the file hello_world.cpp in some directory called code. I want to be able to compile it using both Clang and GCC, but compilation with Clang fails.

#include <iostream>
//#include <stdfloat>

int main() {
    const double a = 4.0;
    std::cout << "Hello world! a has value " << a << std::endl;
}

To compile, I have

  1. Clang version 17.0.6 downloaded from the official github page with the C and C++ compilers under the paths /opt/clang+llvm/clang+llvm-17.0.6/bin/clang and /opt/clang+llvm/clang+llvm-17.0.6/bin/clang++, respectively
  2. GCC installed via Homebrew, version 14.3.0, with the C and C++ compilers under the path /opt/homebrew/Cellar/gcc@14/14.3.0/bin/gcc-14 and /opt/homebrew/Cellar/gcc@14/14.3.0/bin/g++-14, respectively.

Then, following this tutorial, I set up my ~/.zshrc file like this:

# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/davidtschan/anaconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/Users/davidtschan/anaconda3/etc/profile.d/conda.sh" ]; then
        . "/Users/davidtschan/anaconda3/etc/profile.d/conda.sh"
    else
        export PATH="/Users/davidtschan/anaconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<

set_clang_17() {
    export CC="/opt/clang+llvm/clang+llvm-17.0.6/bin/clang"
    export CXX="/opt/clang+llvm/clang+llvm-17.0.6/bin/clang++"
}

set_gcc_14() {
    export CC="$(brew --prefix gcc@14)/bin/gcc-14"
    export CXX="$(brew --prefix gcc@14)/bin/g++-14"
}

export CFLAGS="-isysroot $(xcrun -show-sdk-path) ${CFLAGS}"
export CXXFLAGS="-isysroot $(xcrun -show-sdk-path) ${CXXFLAGS}"

export LDFLAGS="-L$(xcrun -show-sdk-path)/usr/lib ${LDFLAGS}"

where the entire coda block was already in the ~/.zshrc file. Finally, using this, I open a terminal, run cd code to be in the directory of my .cpp source code, then I run set_gcc_14 and run $CXX -o hello_world hello_world.cpp which compiles without an error. Then I run set_clang_17, and re-run $CXX -o hello_world hello_world.cpp and I get the following error traceback:

In file included from hello_world.cpp:1:
In file included from /opt/clang+llvm/clang+llvm-17.0.6/bin/../include/c++/v1/iostream:43:
In file included from /opt/clang+llvm/clang+llvm-17.0.6/bin/../include/c++/v1/ios:221:
In file included from /opt/clang+llvm/clang+llvm-17.0.6/bin/../include/c++/v1/__ios/fpos.h:14:
In file included from /opt/clang+llvm/clang+llvm-17.0.6/bin/../include/c++/v1/iosfwd:106:
In file included from /opt/clang+llvm/clang+llvm-17.0.6/bin/../include/c++/v1/__std_mbstate_t.h:14:
/opt/clang+llvm/clang+llvm-17.0.6/bin/../include/c++/v1/__mbstate_t.h:51:5: error: "We don't know how to get the definition of mbstate_t without <wchar.h> on your platform."

The error goes on, I just put in a snippet. I guess it has something to do with the linker because when I run set_clang_17 and then run

$CXX -o hello_world hello_world.cpp -isysroot $(xcrun -show-sdk-path) -L$(xcrun -show-sdk-path)/usr/lib

the program can compile. I don't understand where the problem comes from, i.e. why it compiles when I make the root and linker paths explicit. Why do I have this behavior?

I expect set_clang_17 to give me the correct configuration so that I can compile hello_world.cpp using both clang++ and g++ using my setting from the ~/.zshrc file.

3
  • The first line of the traceback should read In file included from hello_world.cpp:1:, sorry about that! Commented Aug 16 at 15:14
  • 2
    Recommendation: When you find there is something missing from the question, edit the question and add it. Commented Aug 16 at 15:27
  • This is a really clumsy way of using multiple compilers. Cmake presets are a lot cleaner. Commented Aug 16 at 16:17

1 Answer 1

3

Because gcc on brew is built with --with-sysroot, pointing it to a default sysroot other than /.

We can even see this by running strings $(which gcc-14) | fgrep .sdk:

../configure [...] --with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX15.sdk

Upstream clang is just not built that way, so it has its sysroot set to /.


Separate note: you can also use --sysroot=... in place of -isysroot+-L.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.