链接使用不同预处理器标志或 C 标准构建的库

Posted

技术标签:

【中文标题】链接使用不同预处理器标志或 C 标准构建的库【英文标题】:Linking libraries built with different preprocessor flags or C standards 【发布时间】:2013-01-24 08:18:22 【问题描述】:

场景 1: 我想将一个新库(libA)链接到我的程序中,libA 是使用带有 -std=gnu99 标志的 gcc 构建的,而我的程序的当前库是在没有该选项的情况下构建的(假设 gcc 默认使用 -std=gnu89 )。

场景 2: libB 是使用一些预处理器标志构建的,如“-D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED”以启用 XPG4 功能,例如msg_control 结构 msghdr 的成员。虽然 libC 不是在没有这些预处理器标志的情况下构建的,但它与 libB 相关联。

是错误的吗? 我关心的主要是结构定义不匹配。

谢谢。

【问题讨论】:

我为不同的优化做了很多,其中一个关键例程比程序的其余部分优化得更精细。 谢谢米哈伊尔,是的,我知道它应该在不同优化标志的情况下工作。我已经更新了我的问题,我担心的是结构定义不匹配。 【参考方案1】:

场景 1 对您来说是完全安全的。 GCC 中的std= 选项检查代码与标准的兼容性,但与 ABI 无关,因此您可以随意将预编译代码与不同的 std 选项结合使用。

场景 2 可能不安全。我这里只举一个简单的例子,实际情况可能要复杂得多。

考虑一下,你有一些功能,比如:

#ifdef MYDEF
int foo(int x)  ... 
#else
int foo(float x)  ... 
#endif

然后你编译 a.o-DMYDEFb.o 没有,并且函数 bara.o 调用函数 foob.o。接下来,您将其链接在一起,一切似乎都很好。然后在运行时一切都失败了,您可能很难调试为什么要从一个模块传递 int ,而期望在被调用方端浮动。

一些更棘手的情况可能包括条件定义的结构字段、调用约定、全局变量大小。

附:假设您所有的源代码都是用相同的语言编写的,只改变标准选项和宏定义。结合 C 和 C++ 代码有时真的很棘手,同意 Mikhail 的观点。

【讨论】:

【参考方案2】:

我遇到的结构定义不匹配的几次是在组合 C 和 C++ 代码时,在这些情况下,有一个明确的警告,表明正在发生可怕的事情。 像

/usr/lib/gcc/i586-suse-linux/4.3/../../../../i586-suse-linux/bin/ld: Warning: size of symbol `tree' changed from 324 in /tmp/ccvx8fpJ.o to 328 in gpu.o

See that question.

【讨论】:

有趣,我做了一个实验,但没有看到这样的警告。但是我的实验只使用了 C 和 gcc。

以上是关于链接使用不同预处理器标志或 C 标准构建的库的主要内容,如果未能解决你的问题,请参考以下文章

有 C++ 标准库 ifdef 或 ifndef 预处理器指令吗?

python有关数据预处理的库

Xcode:根据预处理器标志从资产目录中排除构建中的图像

如何使用命令行将“其他链接器标志”添加到 xcode 项目?

如何使用 C 预处理器找到库的完整路径?

Makefile:来自相同源的两个目标使用不同的标志编译两次