apple-clang not exposing __apple_build_version__
Issue and reason
We figured out apple-clang version 12 and 14 (tested on both) do not expose __apple_build_version__ define.
It is an issue because CMake bases its heuristics on this variable to differentiate clang and apple-clang. Which leads some projects to fail due to clang parameters given to apple clang (i.e: --start-group linker parameter).
Steps to reproduce
We built apple-clang with:
# Build Apple Clang
RUN wget -O osxcross.zip https://github.com/tpoechtrager/osxcross/archive/${OSXCROSS_COMMIT_HASH}.zip \
&& unzip osxcross.zip \
&& rm osxcross.zip \
&& mv osxcross-${OSXCROSS_COMMIT_HASH}/ osxcross \
&& cd osxcross \
&& UNATTENDED=1 \
CLANG_VERSION=${CLANG_VERSION} \
ENABLE_CLANG_INSTALL=1 \
ENABLE_FULL_BOOTSTRAP=1 \
PORTABLE=1 \
INSTALLPREFIX=${CLANG_INSTALL_PREFIX} \
./build_apple_clang.sh
And tested with a simple .cpp file:
#include <iostream>
int main(void)
{
#ifdef __apple_build_version__
std::cout << "__apple_build_version__ set" << std::endl;
#else
std::cout << "__apple_build_version__ NOT set" << std::endl;
#endif
#ifdef __clang__
std::cout << "__clang__ set" << std::endl;
#else
std::cout << "__clang__ NOT set" << std::endl;
#endif
}
The cpp was pre-processed into our osxcross docker with command:
/usr/local/osxcross/bin/x86_64-apple-darwin20.2-clang++ -E testCompiler.cpp
And the output (curated) is quite clear:
# 2 "testCompiler.cpp" 2
int main(void)
{
std::cout << "__apple_build_version__ NOT set" << std::endl;
std::cout << "__clang__ set" << std::endl;
}
Did we forget a parameter when building apple-clang?
Afaik __apple_build_version__ is only defined by Apple's internal build system. There is no option to expose it otherwise: https://github.com/search?q=repo%3Aswiftlang%2Fllvm-project%20__apple_build_version__&type=code
The CMake check should be fixed instead.
I totally agree the CMake check is not a proper way to do it. Nonetheless, since we are building apple-clang, I'd tend to think it should be done so the executable behaves the same without differences. Thank you for your answer.
@tpoechtrager if you agree, we can try and patch the build-clang script to, when building apple-clang, expose this variable.
I am not a fan of defining __apple_build_version__ on our own. I'm not exactly sure what it does, nor do I know the specifics of how Apple builds their compiler.
Not having the compiler recognized as Apple Clang shouldn't be a problem - the relevant project should be fixed instead.
If you still want to experiment with defining __apple_build_version__, you could add the following:
fargs.push_back("-D__apple_build_version__=1");
to wrapper/target.cpp right before
if (SDKOSNum >= OSVersion(14, 0) && clangversion < ClangVersion(17, 0)) {
Then re-build the wrapper with:
./wrapper/build_wrapper.sh
Verify __apple_build_version__ is defined:
$ OCDEBUG=1 xcrun clang
osxcross: debug: --> /home/thomas/dev/osxcross/target/bin/x86_64-apple-darwin24.5-clang
osxcross: debug: <-- /opt/llvm/20.1.5/bin/clang-20 (clang) -target x86_64-apple-darwin24.5 -isysroot /home/thomas/dev/osxcross/target/bin/../SDK/MacOSX15.5.sdk -isystem /home/thomas/dev/osxcross/target/bin/../SDK/MacOSX15.5.sdk/usr/include/c++/v1 -isystem /opt/llvm/20.1.5/bin/../lib/clang/20/include -mmacosx-version-min=10.13.0 -arch x86_64 -fuse-ld=lld -D__apple_build_version__=1 -Wno-liblto
osxcross: debug: === time spent in wrapper: 0.052552 ms
clang: error: no input files
Thanks again for your answer, I will try this and present a PR.
I totally understand the impact is impossible to analyze, I'll add your proposal between a ifdef EXPOSE_APPLE_CLANG_VERSION so osxcross users can opt-in only if they want it.
That'd be fine 👍
A runtime define (I.e. if you set an environment like OSXCROSS_PRETEND_TO_BE_APPLE_CLANG=1) instead of a compile time define, might be even more useful: people could switch it on when they think they need it, without recompiling.
Please see PR : https://github.com/tpoechtrager/osxcross/pull/464