【问题标题】:gcc static library linking vs dynamic linkinggcc 静态库链接与动态链接
【发布时间】:2013-04-16 02:35:55
【问题描述】:

我的构建环境是 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静态链接会报错?

【问题讨论】:

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


    【解决方案1】:

    为什么用libcunit.a静态链接会报错

    问题在于您的libcunit.a 是在一个古老的 Linux 系统上构建的,并且依赖于从 libc删除的符号(这些符号在 glibc-2.2 中使用,并且是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
    

    【讨论】:

    • 嗨,我实际上是从源代码 (cunit.sourceforge.net) 编译 cunit 项目。它不是给我的预编译二进制文件。我使用自动工具来安装它。还有一个问题, libc.a 没有 ctype_b 符号。但我没有要求 libc 静态链接到我的测试应用程序。所以应该是动态链接到libc.so.6吧?
    【解决方案2】:

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

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

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

    gcc -o test test.c -L/usr/local/lib -Wl,-Bstatic -lcunit -Wl,-Bdynamic -labc -lyz
    

    【讨论】:

    • 这个答案不正确,问题与图书馆订购无关
    • @Employed Russian:您在哪里看到我的回答是解决“图书馆订购” 的问题?建议的命令行只是 OP 命令行的复制粘贴,带有一些编辑/添加的标志,但没有更改链接顺序。
    • 如果您直接列出libcunit.a,则不需要-Wl,-Bstatic(就像OP 所做的那样)。
    猜你喜欢
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多