如何通过#define指令检测LLVM及其版本?
我认为这个问题很清楚。我正在尝试编写一个编译器检测标头,以便能够在应用程序中包含有关使用哪个编译器以及哪个版本的信息。
这是我正在使用的代码的一部分:
/* GNU C Compiler Detection */
#elif defined __GNUC__
#ifdef __MINGW32__
#define COMPILER "MinGW GCC %d.%d.%d"
#else
#define COMPILER "GCC %d.%d.%d"
#endif
#define COMP_VERSION __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__
#endif
可以像这样使用:
printf(" Compiled using " COMPILER "\n", COMP_VERSION);
有没有办法检测 LLVM 及其版本?还有叮当声?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
您可以使用 gcc verison 宏来代替构建版本字符串:
Clang:
GCC:
注意
__VERSION__
由 gcc 标准化,因此其他编译器 (Microsoft Visual C++) 可能不存在。Instead of building the version string, you could use the gcc verison macro:
Clang:
GCC:
Note
__VERSION__
is standardized by gcc, so it likely won't exist for other compilers (Microsoft Visual C++).__llvm__
和__clang__
宏分别是检查 LLVM 编译器(llvm-gcc 或 clang)或 clang 的官方方法。__has_feature
和__has_builtin
是使用 clang 时检查可选编译器功能的推荐方法,它们记录在 此处。请注意,您可以使用以下命令找到 gcc、llvm-gcc 和 clang 的内置编译器宏列表:
这会预处理一个空字符串并吐出编译器定义的所有宏。
The
__llvm__
and__clang__
macros are the official way to check for an LLVM compiler (llvm-gcc or clang) or clang, respectively.__has_feature
and__has_builtin
are the recommended way of checking for optional compiler features when using clang, they are documented here.Note that you can find a list of the builtin compiler macros for gcc, llvm-gcc, and clang using:
This preprocesses an empty string and spits out all macros defined by the compiler.
我在这里找不到答案,只能链接到答案,因此为了完整起见,这里是答案:
我目前得到:
I cannot find an answer here, only links to answers, so for completeness, here is the answer:
I get currently:
对于 clang,您不应该测试其版本号,您应该使用 功能检查宏来检查您想要的功能。
For clang, you shouldn't test its version number, you should check for features you want with feature checking macros.
来自 InitPreprocessor.cpp 的片段:
我没有不过,没有找到任何方法来获取 llvm 和 clang 本身的版本..
Snippet from InitPreprocessor.cpp:
I didn't find any way to get the version of llvm and clang itself, though..
查看预定义编译器宏页面,选择编译器 -> Clang。还有关于标准、编译器、库、操作系统、体系结构等的许多其他宏的信息。
Take a look at the Pre-defined Compiler Macros page, select Compilers->Clang. There is information on many other macros for standards, compilers, libraries, OS, architectures and more.
请注意,如果您使用 llvm 破解字节码,从而使用
#include
llvm 包含文件,则可以检查llvm/Config/llvm-config.h
中的宏>。具体来说:Note that if you're using llvm to hack on bytecode, and thus
#include
ing llvm include files, you can check the macros inllvm/Config/llvm-config.h
. And concretely:我同意最好的选择是使用具有功能宏,而不是版本宏。
boost 示例:
但是不管怎样,如果你需要编译版本,你可以使用boost.predef:
输出示例:
I agree that the best choice is to use has feature macroses, not version macroses.
Example with boost:
But anyway, if you need compiler version, you can use boost.predef:
Output examples:
每个回答正确做法是使用特征检测宏(如 __has_feature、
__has_builtin
等)的人都是对的。如果这对于您的用例来说是可能的,那么您应该这样做。也就是说,有时 clang 不会公开任何特定于您要检查的内容的内容。例如,无法判断特定的 SSE/AVX 或 NEON 功能是否可用(是的,不时添加新功能;CPU 支持的指令是固定的,但有时添加使用现有指令的新函数来填补 API 中的漏洞)。或者可能存在错误并且 clang 生成了不正确的机器代码。实际上,我们在 SIMDe 项目中经常遇到此类问题。
不幸的是,您不能依赖
__clang_major__
/__clang_minor__
/__clang_patchlevel__
。像 Apple 这样的供应商采用 clang 并将其重新打包为自己的编译器,并使用自己的版本号,并且当他们这样做时,他们通常也会更改__clang_*__
版本以匹配他们的编译器版本,不是上游 clang 的。例如,Apple clang 4.0 实际上是重新打包的 clang 3.1,但他们将 __clang_major__ 设置为 4,将__clang_minor__
设置为 0。我发现的最佳解决方案是使用该功能检测代码来检测完全不相关的功能,这些功能恰好添加到与您真正想要检测的版本相同的版本中。我这样做已经有一段时间了,但今天早些时候我终于整理了 一个标头将所有逻辑保留在一个地方。它是 SIMDe 的一部分,但没有任何依赖关系,并且是公共领域 (CC0)。我可能会忘记在将来进行任何改进来更新此答案,因此请检查当前版本的存储库,但这是现在的样子:
Everyone who has answered that the right thing do it is to use feature detection macros like
__has_feature
,__has_builtin
, etc., is right. If that's possible for your use case, that's what you should do.That said, there are times when clang doesn't expose anything specific to what you're trying to check. For example, there is no way to tell if a particular SSE/AVX or NEON function is available (and yes, new ones are added from time to time; the instructions the CPU supports are fixed, but sometimes new functions using existing instructions are added to plug a hole in the API). Or maybe there was a bug and clang was generating incorrect machine code. We actually run into these types of issues a fairly often in the SIMDe project.
Unfortunately you can't rely on
__clang_major__
/__clang_minor__
/__clang_patchlevel__
. Vendors like Apple take clang and repackage it as their own compiler with their own version numbers, and when they do they generally also change the__clang_*__
versions to match their compiler version, not upstream clang's. For example, Apple clang 4.0 is really a repackaged clang 3.1, but they set__clang_major__
to 4 and__clang_minor__
to 0.The best solution I've found is to use the feature detection code to detect completely unrelated features which just so happen to be added in the same version as what you really want to detect. I've been doing this for a while, but earlier today I finally put together a header to keep all that logic in one place. It's part of SIMDe, but has no dependencies whatsoever and is public domain (CC0). I'll probably forget to update this answer with any improvements in the future, so please check the repo for the current version, but here is what it looks like right now:
与 semequ 解决方案类似,我们可以构建宏,通过直接利用 维基百科数据(基于 llvm 项目的 CMakeLists 构建,例如 这个)。
该解决方案避免了处理专有 Apple clang 合并来自不同版本的 LLVM clang 的属性或诊断标志的情况。
Similarly to semequ solution, we can build macros that will detect the LLVM clang version while using Apple clang by directly leveraging the Wikipedia data (which is built on the CMakeLists of the llvm-project, like this one).
That solution avoids dealing with situations where the proprietary Apple clang would incorporate Attributes or Diagnostic flags coming from a different version of LLVM clang.