我的构建环境是 CentOS 5 。我有一个名为libcunit的第三方库。我用autotools安装它,它生成libcunit.a
和libcunit.so
。我有自己的应用程序链接到一堆共享库。 libcunit.a
位于当前目录中,libcunit.so
和其他共享库位于/usr/local/lib/
中。当我编译时:
gcc -o test test.c -L. libcunit.a -L/usr/local/lib -labc -lyz
我收到了链接错误:
libcunit.a(Util.o): In function `CU_trim_left':
Util.c:(.text+0x346): undefined reference to `__ctype_b'
libcunit.a(Util.o): In function `CU_trim_right':
Util.c:(.text+0x3fd): undefined reference to `__ctype_b'
但是当我用.so
编译时,如:
gcc -o test test.c -L/usr/local/lib -lcunit -labc -lyz
它编译得很好并且运行良好。
为什么在与libcunit.a
静态链接时会出错?
答案 0 :(得分:6)
为什么在与
静态链接时会出错libcunit.a
问题是你的libcunit.a
是建立在一个古老的Linux系统上的,并且取决于libc
中删除的符号(glibc-2.2
中使用了这些符号1}},并在10年前从glibc-2.3
中删除了。更准确地说,这些符号是hidden
。它们可用于动态链接到旧二进制文件(例如libcunit.so
),但没有新代码可以静态链接到它们(您无法创建引用它们的新可执行文件或共享库)。
您可以这样观察:
readelf -Ws /lib/x86_64-linux-gnu/libc.so.6 | egrep '\W__ctype_b\W'
769: 00000000003b9130 8 OBJECT GLOBAL DEFAULT 31 __ctype_b@GLIBC_2.2.5
readelf -Ws /usr/lib/x86_64-linux-gnu/libc.a | egrep '\W__ctype_b\W'
# no output
答案 1 :(得分:3)
没有注意到libcunit.a
实际上是在你的情况下找到的,而linakge的问题则在CUnit库中。雇用俄语是绝对正确的,他不是在谈论预编译的二进制文件。我们知道您自己构建了它。然而,CUinit本身似乎依赖于glibc
的符号,该符号不再用于静态链接。因此,您只有两个选项:
尽管如此,我对你的静态链接风格的建议仍然适用。 -L.
通常是不良做法。 CUnit是第三方库,不应放在包含项目源文件的目录中。它应该以与动态版本相同的方式安装,即您在libcunit.so
中拥有/usr/local/lib
。如果您在CUnit的配置阶段向Autotools提供prefix
,那么Autotools会正确安装所有内容。因此,如果要静态链接CUnit,请考虑使用以下格式进行链接:
gcc -o test test.c -L/usr/local/lib -Wl,-Bstatic -lcunit -Wl,-Bdynamic -labc -lyz