获取苹果clang版本及相应的上游LLVM版本

74

我想知道苹果在我的Macbook上安装了哪个版本的clang,以查看可用的c++11和/或c++14功能。

我输入了这个命令:

clang --version

//----response
Apple LLVM version 7.0.0 (clang-700.1.76)     
Target: x86_64-apple-darwin15.0.0    
Thread model: posix

但是我不理解 (clang-700.1.76) 是什么意思。 我该如何将这个代码转换为 clang 版本?

这是一个网站,您可以在其中查看在 clang 版本中可用的 C++ 功能 http://clang.llvm.org/cxx_status.html


1
显然,它曾经报告基于上游LLVM版本的信息:Xcode clang版本,但正如您所发现的那样,它不再提供这些信息。我猜测可能是3.6或3.7。 - melak47
将标题更改为“获取Apple clang版本及相应的上游LLVM版本”,以便概括事情。 - smci
10个回答

32

23

这是我找到的最佳清单,它将Apple的clang版本与LLVM版本相对应:

https://trac.macports.org/wiki/XcodeVersionInfo

以前的版本会说它们对应的是哪个LLVM版本,但从7.0开始,Apple决定不再这样做。他们甚至将__clang_version__和相关的预处理器宏定义为Apple版本号,而非LLVM版本。所以它们对于此也毫无用处。

不幸的是,似乎唯一确定是否具有某个功能的方法是尝试并检查其是否有效。例如,7.0.2仍未启用默认的OpenMP(虽然可以启用),因此我猜它仍是3.6,而不是3.7。


自Xcode 7(2015年)以来,该页面就没有列出相应的LLVM版本,不像https://en.wikipedia.org/wiki/Xcode#Toolchain_versions。 - chrstphrchvz

9

就像pkolbus所暗示的那样,你可以查看/src/CMakeLists.txt来猜测相应的Clang版本。例如,苹果Clang800.0.38800.0.42.1似乎都基于Clang 3.9.0,据此推断。

if(NOT DEFINED LLVM_VERSION_MAJOR)
  set(LLVM_VERSION_MAJOR 3)
endif()
if(NOT DEFINED LLVM_VERSION_MINOR)
  set(LLVM_VERSION_MINOR 9)
endif()
if(NOT DEFINED LLVM_VERSION_PATCH)
  set(LLVM_VERSION_PATCH 0)
endif()
if(NOT DEFINED LLVM_VERSION_SUFFIX)
  set(LLVM_VERSION_SUFFIX svn)
endif()

1
哪个 /src/CMakeLists.txt - Walter
@Walter 是来自 Clang 的那个人。我在答案中链接了两个示例。 - Franklin Yu

7

请查看https://zh.wikipedia.org/wiki/Xcode#工具链版本


Xcode    cctools[93]      ld64[94]      LLVM[85]      Clang version string[95] 
8.3.3    898              278.4         3.9.0svn[85]  8.1.0 (clang-802.0.42)[80]
9.0      900              302.3         4.0.0?[86]    9.0.0 (clang-900.0.37)[80]
9.1      900              302.3.1       4.0.0?[87]    9.0.0 (clang-900.0.38)[80]
9.2      900              305           4.0.0?[88]    9.0.0 (clang-900.0.39.2)[80]
9.3      906              351.8         5.0.2?[89]    9.1.0 (clang-902.0.39.1)[80]
9.3.1    906              351.8         5.0.2?[89]    9.1.0 (clang-902.0.39.1)[80]
9.4      906              351.8         5.0.2?[90]    9.1.0 (clang-902.0.39.2)[80]
9.4.1    906              351.8         5.0.2?[90]    9.1.0 (clang-902.0.39.2)[80]
10.0     921.0.1          409.12        6.0.1?[91]    10.0.0 (clang-1000.11.45.2)[80]
10.1     921.0.1          409.12        6.0.1?[92]    10.0.0 (clang-1000.11.45.5)[80]

例如,Apple CLang 10.x 是基于 LLVM 6.0.1 的。

5
首先,我想说Daniel Frey的回答绝对是正确的;尽可能使用__has_feature__has_extension等。Clang语言扩展页面记录了您可以检查的不同内容,这应该是您的首选解决方案。
话虽如此,有时确实需要检查版本。例如,有时需要解决在较新版本中已修复或仅出现在较新版本中的编译器错误。有时会添加新功能;例如,在clang 9之前, __builtin_constant_p diagnose_if 属性一起使用无法正常工作。有时添加功能但没有相应的检查。
我真希望Clang能够将上游版本号公开为预处理器宏,这样我们就可以可靠地处理类似的情况,但他们没有。您可以手动创建一个苹果版本号到上游版本号的映射表,这是其他一些答案提出的,但它有一些非常明显的缺点。对我来说,致命的缺陷是它并不适用于除苹果Clang之外的编译器;现在有很多基于Clang的编译器(IBM XL C/C ++、一些新的PGI / NVIDIA编译器、下一代英特尔C/C ++等)。
我的解决方法是使用功能检测宏来估计版本号。例如, -Wimplicit-const-int-float-conversion 在clang 11中添加,因此如果 __has_warning(“-Wimplicit-const-int-float-conversion”)为真,则我们可以假定上游clang版本为> = 11。同样,clang 10添加了 -Wmisleading-indentation ,clang 9开始定义 __FILE_NAME__ 预处理器宏等。
我创建了一个包含必要逻辑的小标题,它是公共领域(CC0),虽然它是我的一个项目(SIMDe)的一部分,但它不依赖于任何其他文件,因此您可以自由地将其用于自己的项目中,而无需复制整个SIMDe。

显然,该文件需要针对每个版本的clang进行新的测试,因此如果您需要检查更新的编译器,则需要定期更新。建议从SIMDe git存储库获取最新版本(我不太可能保持此答案最新),但目前的检查如下所示:

#if defined(__clang__) && !defined(SIMDE_DETECT_CLANG_VERSION)
#  if __has_warning("-Wformat-insufficient-args")
#    define SIMDE_DETECT_CLANG_VERSION 120000
#  elif __has_warning("-Wimplicit-const-int-float-conversion")
#    define SIMDE_DETECT_CLANG_VERSION 110000
#  elif __has_warning("-Wmisleading-indentation")
#    define SIMDE_DETECT_CLANG_VERSION 100000
#  elif defined(__FILE_NAME__)
#    define SIMDE_DETECT_CLANG_VERSION 90000
#  elif __has_warning("-Wextra-semi-stmt") || __has_builtin(__builtin_rotateleft32)
#    define SIMDE_DETECT_CLANG_VERSION 80000
#  elif __has_warning("-Wc++98-compat-extra-semi")
#    define SIMDE_DETECT_CLANG_VERSION 70000
#  elif __has_warning("-Wpragma-pack")
#    define SIMDE_DETECT_CLANG_VERSION 60000
#  elif __has_warning("-Wbitfield-enum-conversion")
#    define SIMDE_DETECT_CLANG_VERSION 50000
#  elif __has_attribute(diagnose_if)
#    define SIMDE_DETECT_CLANG_VERSION 40000
#  elif __has_warning("-Wcomma")
#    define SIMDE_DETECT_CLANG_VERSION 39000
#  elif __has_warning("-Wdouble-promotion")
#    define SIMDE_DETECT_CLANG_VERSION 38000
#  elif __has_warning("-Wshift-negative-value")
#    define SIMDE_DETECT_CLANG_VERSION 37000
#  elif __has_warning("-Wambiguous-ellipsis")
#    define SIMDE_DETECT_CLANG_VERSION 36000
#  else
#    define SIMDE_DETECT_CLANG_VERSION 1
#  endif
#endif /* defined(__clang__) && !defined(SIMDE_DETECT_CLANG_VERSION) */

我认为这种方法最大的问题实际上与我所知道的所有其他检测上游clang版本的尝试都存在共同之处:并不一定有一个对应于所涉及代码的clang版本。据我所知,大多数基于clang的编译器实际上并不是基于发布版,而是某个随机提交(可能是他们想要基于其工作的分支的最新提交)。这意味着,例如,如果在clang $N开发周期后期修复了问题,则苹果的分支通常与clang $N相同,但不包含错误修复。相反,也许苹果会从clang $N+1中回溯修复,并且在clang $N中存在的错误将在苹果的版本中得到修复。

2

可以尝试使用--verbose选项来编译某些文件。

例如: c++ --verbose -c test1.cpp

Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
 "/Library/Developer/CommandLineTools/usr/bin/clang" -cc1 -triple x86_64-apple-macosx10.10.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -main-file-name test1.cpp -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 253.9 -v -dwarf-column-info -coverage-file /Users/az/ctest/test1.cpp -resource-dir /Library/Developer/CommandLineTools/usr/bin/../lib/clang/7.0.2 -stdlib=libc++ -fdeprecated-macro -fdebug-compilation-dir /Users/az/ctest -ferror-limit 19 -fmessage-length 130 -stack-protector 1 -mstackrealign -fblocks -fobjc-runtime=macosx-10.10.0 -fencode-extended-block-signature -fcxx-exceptions -fexceptions -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -o test1.o -x c++ test1.cpp
clang -cc1 version 7.0.2 based upon LLVM 3.7.0svn default target x86_64-apple-darwin14.5.0

它会打印出LLVM svn版本(在我们的示例中为3.7.0)


不再适用于当前的Apple clang,请参见https://gist.github.com/webmaster128/7734385cdd7eee4cfc6c6171725ffb1c。 - Simon Warta

1
如果您在编译器上使用strings命令,您可能会得到LLVM版本。例如,如果您有clang版本,该版本标识自己为"Apple LLVM version 7.0.2 (clang-700.1.81)",则strings的输出将具有此值。
LLVM 3.7.0svn

这似乎无法与版本 Apple LLVM version 7.3.0 (clang-703.0.29)兼容。

当前的Apple clang字符串仅包含二进制名称。或者我在这里漏掉了什么?https://gist.github.com/webmaster128/73dee3783694b04987290e5b120aa3e5 - Simon Warta
@SimonWarta,在/usr中的Xcode命令行工具实际上只是指向安装在Xcode包中真正的工具的快捷方式。使用strings "$(xcrun --find clang)" | grep LLVM - rgov

0
作为您的终端输出
clang --version
//----response
Apple LLVM version 7.0.0 (clang-700.1.76)     
Target: x86_64-apple-darwin15.0.0    
Thread model: posix

第一行 "Apple LLVM version 7.0.0 (clang-700.1.76)" 的意思是: 你的 Xcode7.1 带有嵌入式的 Clang7.0.0Clang7.0.0 标识符:clang-700.1.76)。

从这个 网站,我知道你的 Clang 版本是 7.0.0。 如果 Clang 版本大于等于 Clang5.0那么该 Clang 支持 C++11 或 C++14


0
如果你安装了CLion,在它的首选项-工具链中,你可能会看到“调试器”作为捆绑的LLDB 7.0.1
我相信这是当前的苹果clang版本。(例如Apple LLVM版本10.0.1)

-1

编译器的(Apple)版本号大多数情况下是无用的,因为您还需要考虑您的代码是使用libstdc++还是libc++(或任何其他标准库)进行编译 - 以及这些库的哪个版本。

如果您想测试语言或库功能,则最好检查其他定义的值,例如__cplusplus__cpp_constexpr__cpp_variadic_templates等。虽然不完美,但根据我的经验,它似乎工作得更好(如果您想要可移植性),并且所有主要编译器的支持正在改善。

每个C ++标准版本都为__cplusplus定义一个值,一些编译器使用中间值来表示“我们已经开始使用C ++14,但我们还没有到达那里”。在需要时使用>=进行测试。

其他功能测试宏类似,您可以在N4440找到当前版本。但并非所有编译器都实现了N4440。


18
“编译器的版本号大多数情况下是没什么用的。”什么?我想知道他们问题追踪系统中的一个bug是否已经被修复。如果我知道这是clang编译器的bug(与constexpr或其他什么有关),那它怎么可能“大多数情况下是没什么用的”?这是一个很大、没有依据的说法。 - Ven
13
@Ven 这是指在这个问题的上下文中,而不是普遍适用。当涉及到标准库时,版本号对于特性检测来说大多是无用的,因为编译器版本号不能(也不可能)包含使用的libstdc++版本。此外,由于苹果公司使用的版本号方案与Clang不同,您不能简单地将苹果的版本号与Clang的错误数据库进行匹配。 - Daniel Frey
3
因为它没有回答如何确定 clang 版本的具体问题,所以被踩了。 - ray
3
@ray OP还写道:“我想了解苹果在我的MacBook中安装了哪个版本的clang,以查看是否可用c++11和/或c++14功能。” 对我来说,这似乎是他想得到答案的问题,而不仅仅是他发布帖子的标题。 此外,从Mike的答案所列出的https://trac.macports.org/wiki/XcodeVersionInfo来看,很明显苹果并没有真正记录他们的Clang版本基于官方Clang版本的情况。 我仍在等待更好的答案来解决OP的问题。 - Daniel Frey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接