【问题标题】:Statically link multiple libraries into one .so将多个库静态链接到一个 .so
【发布时间】:2015-02-22 19:40:27
【问题描述】:

我有一个项目foo,它依赖于a,它又依赖于b,又依赖于c。我的构建脚本 pull/configure/make 以正确的顺序从源代码中提取了三个依赖项,它们编译得很好。

现在,要分发foo.so,我还需要同时分发它的所有依赖项(a.sob.soc.so)。我想构建一个foo.so,其中包含foo 的所有对象及其所有依赖项;这样我就可以分发一个库。

abc都使用autotools,并在src/目录下生成相关的*.o文件,还有一个.libs/目录下包含了一些常用的*.ar, *.lo、*.lai 和 *.so 文件均有效。现在,我正在使用这组 gcc 标志来构建我的foo.so

gcc -shared ./my/src/*.c \
    -I./a/include -I./b/include -I./c/include \
    -L ./a/.libs -L./b/.libs -L./c/.libs \
    -la -lb -lc \
    -o ./foo.so \
    -w -fPIC -m64 \
    -std=c99

(请注意,“-la -lb -lc”只是每个依赖项的“-l”标志,我不只是弄乱标志)。

在结果foo.so 上使用readelf -d 确实表明它依赖于a。鉴于我已经获得了所有依赖项的所有构建文件,我真的觉得我只是缺少一些“在查找要链接的 *.o 文件时包含此路径”的标志。

我尝试了很多方法,老实说,我什至不记得导致它们的不同错误和条件。最有希望的线索是this question,但是在删除我的“-l”行以支持“-Wl,--whole-archive”行之后,我收到了这个错误(注意“a.a”只是*.a for a):

/usr/bin/ld: ./a/.libs/a.a(bands.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
./a/.libs/a.a(bands.o): error adding symbols: Bad value

这对我来说毫无意义,因为这些文件必须是 PIC 才能将它们构建成 *.so,对吧?这些依赖项的构建过程会生成一个 *.so。

如果重要的话,我正在使用 Mint Linux。

【问题讨论】:

  • 如果您有.la 文件,请使用libtool 处理linking。例如,libtool --mode=link gcc -o foo.la ./my/src/*.lo ./a/a.la ./b/b.la ./c/c.la - 要求使用 libtool --mode=compile gcc <cflags> -c file.c 构建源对象

标签: c gcc


【解决方案1】:

错误信息非常清楚需要做什么。

/usr/bin/ld: ./a/.libs/a.a(bands.o): relocation R_X86_64_32S against
`.rodata' can not be used when making a shared object; recompile with -fPIC
                                                      ^^^^^^^^^^^^^^^^^^^^^

./a/.libs/a.a(bands.o): error adding symbols: Bad value

我们作为静态库一部分的目标代码不能放在共享库中,除非它们是使用-fPIC 选项编译的。

【讨论】:

  • 但它不是必须已经编译为 PIC,因为 autotools/make 过程会创建一个 a.so
  • 我不知道 autotools 和 make 是如何设置的。在将生成的目标文件添加到静态库之前编译文件时,他们显然没有将-fPIC 添加到编译器。
【解决方案2】:

在此处回答者的帮助下,我得到了一个可行的解决方案。我从根本上误解了 autotools 会生成两组 *.o 文件,一组是 PIC,一组不是。每一个的位置都在 *.lo 文件中。我的依赖项(abc)都是用自动工具构建的,我需要链接 PIC 版本,而不是组合的静态 *.a 版本。

我还需要使用 libtool 将构建过程分成两部分。编译阶段只是为了构建我的代码,链接器阶段查看依赖项的 PIC 版本。

我最终没有得到一个漂亮的脚本,但如果有人遇到同样的情况,我丑陋的 gcc 行看起来像。希望这将是一个跳跃点,而不是我想出的……可怕的东西。

find ./my/src -name "*.c" -exec \
libtool --mode=compile gcc -c -O -g \
    -I./a/include -I./b/include -I./c/include \
    -L./a/.libs/*.lo -L./b/.libs/*.lo -L./c/.libs/*.lo \
    -la -lb -lc \
    -w -m64 \
    -std=c99 \
    {} \;

gcc \
    -g -O -w -fPIC -m64 -std=c99 -shared \
    -o ./foo.so \
    $(find . -wholename "*.libs/*.o");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2021-06-13
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2012-07-29
    • 1970-01-01
    相关资源
    最近更新 更多