3

我的构建环境是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

4

2 回答 2

6

为什么静态链接时会出错libcunit.a

问题是你libcunit.a是建立在一个古老的 Linux 系统上的,并且依赖于已被删除libc符号(这些符号被用于,并且在 10 多年前glibc-2.2被删除)。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
于 2013-04-16T04:50:54.287 回答
3

没有注意到libcunit.a实际上在您的案例中找到了,而 linakge 的问题在于 CUnit 库本身。使用俄语是绝对正确的,他在这里不是在谈论预编译的二进制文件。我们了解您是自己构建的。但是,CUinit 本身似乎依赖于glibc不再可用于静态链接的符号。因此,您只有 2 个选项:

  1. 向 CUnit 的开发人员提交报告并要求他们修复它;
  2. 使用动态链接。

尽管如此,我对您的静态链接风格的建议仍然适用。-L.通常是不好的做法。CUnit 是第 3 方库,不应放置在包含项目源文件的目录中。它应该以与动态版本相同的方式安装,即就像您libcunit.so/usr/local/lib. 如果您prefix在 CUnit 的配置阶段向 Autotools 提供,那么 Autotools 将正确安装所有内容。因此,如果您想与 CUnit 进行静态链接,请考虑采用以下形式:

gcc -o test test.c -L/usr/local/lib -Wl,-Bstatic -lcunit -Wl,-Bdynamic -labc -lyz
于 2013-04-16T03:22:30.373 回答