How can I reliably determine the version of clang during preprocessing?

Apparently, the clang associated with __clang_major__ does not take into account the __clang_major__ and __clang_minor__ values ​​upstream, and instead reports some version oriented to the Xcode user.

Here are links for various MacPorts clang installations. They seem to respect up release identifiers. I get similar values ​​when testing on Linux.

 ➜ prohibit-clang-3.2 /opt/local/bin/clang++-mp-3.2 -dM -E -xc /dev/null | grep __clang_m #define __clang_major__ 3 #define __clang_minor__ 2 ➜ prohibit-clang-3.2 /opt/local/bin/clang++-mp-3.3 -dM -E -xc /dev/null | grep __clang_m #define __clang_major__ 3 #define __clang_minor__ 3 ➜ prohibit-clang-3.2 /opt/local/bin/clang++-mp-3.4 -dM -E -xc /dev/null | grep __clang_m #define __clang_major__ 3 #define __clang_minor__ 4 

However, for some reason, Apple provided clang with the __clang_major__ and __clang_minor__ , which track the __clang_minor__ version, rather than the basic clang revision:

 ➜ prohibit-clang-3.2 /Applications/Xcode-4.6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -dM -E -xc /dev/null | grep __clang_m #define __clang_major__ 4 #define __clang_minor__ 2 ➜ prohibit-clang-3.2 /Applications/Xcode-4.6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ --version Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn) Target: x86_64-apple-darwin12.5.0 Thread model: posix ➜ prohibit-clang-3.2 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -dM -E -xc /dev/null | grep __clang_m #define __clang_major__ 5 #define __clang_minor__ 0 ➜ prohibit-clang-3.2 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ --version Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn) Target: x86_64-apple-darwin12.5.0 Thread model: posix ➜ prohibit-clang-3.2 /usr/bin/clang++ -dM -E -xc /dev/null | grep __clang_m #define __clang_major__ 5 #define __clang_minor__ 0 

This seems rather horrible because it means you cannot write conditional compilation lines, as shown below, that will work exactly with both Apple clover and clang, which is usually created from clang sources or from distro packages:

 #if !defined(__clang__) || (__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ > 2)) // Thing that doesn't work for clang-3.2 due to an optimization bug. #endif 

I would not want to extend this rather awful preprocessor check to the account for two different clang version control schemes, one normal and one Apple. I'm not even sure how I could reliably detect that this is an "Xcode clang", not a regular clang.

Does anyone have any suggestions on how to get around this? Is there a flag to pass to Apple clang, which will instruct him to inform his "true" version? Or did Apple doom us to never be able to reliably use __clang_major__ and __clang_minor__ ? These are not macros that I should use here?

+6
source share

Source: https://habr.com/ru/post/955999/


All Articles