显然,与 Xcode 捆绑的 clang 不尊重上游__clang_major__
和__clang_minor__
值,而是报告某种 Xcode 面向用户的版本。
以下是各种 MacPorts 安装 clang 的值,以供参考。他们似乎尊重上游发布标识符。在 Linux 上进行测试时,我得到了类似的值。
➜ prohibit-clang-3.2 /opt/local/bin/clang++-mp-3.2 -dM -E -x c /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 -x c /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 -x c /dev/null |
grep __clang_m
#define __clang_major__ 3
#define __clang_minor__ 4
但是,出于某种原因,Apple 提供的 clang 具有跟踪 Xcode 版本__clang_major__
的__clang_minor__
版本,而不是基本的 clang 修订:
➜ prohibit-clang-3.2
/Applications/Xcode-4.6.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++
-dM -E -x c /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 -x c /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 -x c /dev/null | grep __clang_m
#define __clang_major__ 5
#define __clang_minor__ 0
这看起来很糟糕,因为这意味着您不能编写像下面这样的条件编译行,这些行将在 Apple 供应的 clang 和从 clang 源或发行包正常构建的 clang 中准确工作:
#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
我讨厌需要扩展已经非常糟糕的预处理器检查以解决两种不同的 clang 版本控制方案,一种是普通的,一种是 Apple 的。我什至不确定如何可靠地检测到这是“Xcode clang”而不是正常的 clang。
有没有人对如何解决这个问题有任何建议?是否有一个标志可以传递给 Apple 的 clang,以指示它报告其“真实”版本?还是苹果注定我们永远无法可靠地使用__clang_major__
和__clang_minor__
?这些不是我应该在这里使用的宏吗?