【问题标题】:Static link libpng into a shared library静态链接 libpng 到共享库
【发布时间】:2018-04-09 09:18:18
【问题描述】:

我已将问题简化为这个最小的 test.c:

#include "png.h"

int function() {
    printf("%ld", (long)png_create_read_struct);
}

编译

gcc -shared -fPIC test.c -o test.so -lm -l:libpng16.a

给出错误

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libpng16.a(pngread.o): relocation R_X86_64_PC32 against symbol `png_sRGB_table' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value

现在,我发现的这个错误的每个答案都归结为“按照它所说的去做,然后用 -fPIC 重新编译”,但正如你所看到的,我已经在这样做了。那么是什么给出的呢?

(上面的输出来自带有 libpng16 的 Ubuntu 17.10。带有 libpng12 的 Ubuntu 16.04 会导致类似的错误。)

【问题讨论】:

  • 不,你还没有这样做。链接器希望libpng16.a 中的对象是 PIC,而它们不是。 这就是它希望你用-fPIC重新编译的东西。
  • 为什么不直接链接 libpng 共享库?
  • @JohnBollinger 所以 apt 包中附带的静态库没有为此做好准备,我必须重新编译我想要静态链接的所有内容?该死。有什么方法可以检查 .a 文件是否是用 -fPIC 编译的? (PS请让您的评论成为答案)

标签: c shared-libraries static-libraries ld static-linking


【解决方案1】:

现在,我找到的针对此错误的每个答案都归结为“按照它所说的去做并使用 -fPIC 重新编译”,但正如您所见,我已经在这样做了。那么是什么给出的呢?

正如我评论的那样,不,事实上你没有已经这样做了。链接器希望从libpng16.a 链接的对象是 PIC,但它们不是。 这就是它希望你用-fPIC重新编译的东西。

虽然可以将 PIC 对象存储在常规存档中,例如 libpng16.a,但这是非常规的。这些文件通常被称为“静态库”并非没有道理。它们通常旨在支持构建静态二进制文件,而不是共享二进制文件,并且 PIC 对象不满足该目的。您不应期望标准包提供的任何此类存档包含 PIC 对象。

无论如何,既然您正在构建一个共享库,那么自然而适当的做法是链接到 libpng 的共享版本。您尝试链接静态库时遇到了一些麻烦,但不清楚原因。无论你想要完成什么,这都是错误的做法,即使它是值得完成的事情。

【讨论】:

  • 对于你的最后一个问题,我需要打包使用旧版本 libpng 的 python 扩展,这些旧版本不再打包在当前的 linux 发行版中。我不明白为什么静态链接会是错误的方法。存在其他选项,但任何使部署复杂化的解决方案都会带来不便。当然必须从源代码编译 libpng 也很不方便,我必须弄清楚什么是“较小的邪恶”解决方案。
  • (哦,如果不是很明显,python 扩展必须是动态库,所以不能选择全部静态)
  • @PedroLopes,链接到静态库是错误的方法,因为它不起作用。正确的方法是链接到适当的共享库。同一个共享库的不同版本可以在系统上共存,一些发行版甚至为某些特定的库提供了包。
【解决方案2】:

用-fPIC编译libpng

user@user_pc:~/Documents$ mkdir libpng
user@user_pc:~/Documents$ cd libpng
user@user_pc:~/Documents/libpng$ wget https://download.sourceforge.net/libpng/libpng-1.6.37.tar.gz
user@user_pc:~/Documents/libpng$ tar xvfz libpng-1.6.37.tar.gz
user@user_pc:~/Documents/libpng$ cd libpng-1.6.37
user@user_pc:~/Documents/libpng/libpng-1.6.37$./configure --prefix=/home/user/Documents/libpng --with-pic=yes
user@user_pc:~/Documents/libpng/libpng-1.6.37$ sudo make

你的二进制文件在~/Documents/libpng/libpng-1.6.37/lib,最有趣的是libpng.a,它现在是用-fPIC编译的。

它还解决了在 Linux 上将 blender 编译为 Python 模块时的问题:

/usr/bin/ld.gold: error: /usr/lib/x86_64-linux-gnu/libpng.a(pngerror.o): requires dynamic R_X86_64_PC32 reloc against 'stderr' which may overflow at runtime; recompile with -fPIC
collect2: error: ld returned 1 exit status

【讨论】:

  • 嗨,Christopher,我在 Ubuntu 上遇到了 Blender 的确切问题,试图编译为 Python 模块。我已经按照您的描述编译了 libpng,但是现在如何修复搅拌机错误?
  • 我需要更明确地解释您想到的搅拌机错误?我有点缺少上下文,但是如果你在谈论 libpng 缺少 fPiC 错误,你必须重新编译搅拌器(作为 Python 模块),但首先你必须确保它会使用你新编译的 fPiC libpng,方法是删除已经存在的 libpng出现在您的电脑中并用您的新版本替换它。它对我有用,但我不得不承认,我没有反转 libpng 交换,所以我仍然有 - fPiC 变体作为我系统的默认值。
  • 谢谢,克里斯托弗。我指的是您在帖子中强调的确切问题。按照您的建议,我将尝试替换 libpng 文件。
  • 再次表示感谢——替换 libpng.a 有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
相关资源
最近更新 更多