我正在尝试为一个大型框架实现回溯功能,该框架用于不同的平台和操作系统。在其中一些中,它与 glibc 链接,而在另一些中,则使用不同的东西(例如 uclibc)。 backtrace() 函数仅存在于前者中。
有什么方法可以判断是否使用了glibc?有#define吗?我无法在 glibc 手册中找到答案。我知道我在编译期间无法获得链接时信息,但我想包含文件必须有所不同。至少必须在某个地方声明回溯。 我想检查它,而不必被迫将显式标志传递给编译器。
包含features.h,它包含您需要的宏,例如
#define __GNU_LIBRARY__ 6
/* Major and minor version number of the GNU C library package. Use
these macros to test for features in specific releases. */
#define __GLIBC__ 2
#define __GLIBC_MINOR__ 4
#define
中有__GNU_LIBRARY__
、__GLIBC__
、__GLIBC_MINOR__
和features.h
(在我的glibc-2.11系统上有6、2和11)。
检查预处理器宏不是一个好的解决方案。 uClibc 和可能的其他 libc 实现定义宏来模仿 glibc(不提供其所有臃肿的功能),其原因与所有浏览器在其用户代理字符串中包含“Mozilla”的原因大致相同:希望看到 glibc 并关闭很多功能的损坏程序如果他们没有看到功能。
相反,您应该编写一个配置脚本来探测
backtrace
并仅在可用时使用它。
根据经验,以下两个都可以在 GCC 6.4 上编译并运行良好:
#include <stdio.h>
int main(void) {
#ifdef __GLIBC__
puts("__GLIBC__");
#endif
return 0;
}
和:
int main(void) {
#ifdef __GLIBC__
puts("__GLIBC__");
#endif
return 0;
}
但当然只有第一个会产生输出。
这必须意味着
__GLIBC__
来自 stdio.h
,其中必须包含 features.h
,另请参阅:features.h 标头的用途是什么?
因此,严格来说,
__GLIBC__
本身并不能清楚地表明使用了glibc,因为即使没有标头,GCC也已经在最终可执行文件中嵌入了运行时对象,例如
crt1.o
,并且这些对象来自glibc。
所以主要缺少的问题是:glibc 是否保证
features.h
被包含在每个标头中?我找不到明确的文档引用。待办事项。
#if defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__MUSL__)
这有点难看并且语法上含糊不清,但很有用。