gcc静态库链接与动态链接

时间:2013-04-16 02:35:55

标签: c gcc linker shared-libraries static-libraries

我的构建环境是 CentOS 5 。我有一个名为libcunit的第三方库。我用autotools安装它,它生成libcunit.alibcunit.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静态链接时会出错?

2 个答案:

答案 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的符号,该符号不再用于静态链接。因此,您只有两个选项:

  1. 向CUnit的开发者提交一份报告,并要求他们修复它;
  2. 使用动态链接。
  3. 尽管如此,我对你的静态链接风格的建议仍然适用。 -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