【问题标题】:Why does C library link order only matter on some systems?为什么 C 库链接顺序仅在某些系统上很重要?
【发布时间】:2014-05-02 16:41:25
【问题描述】:

我的小组正在开发一个程序,该程序使用依赖于 JPEG 库的 JasPer 库。我的同事创建了一个 Makefile,它在构建规则中在 -ljasper 之前列出了 -ljpeg。这在我同事的计算机上运行良好,但不能在我的计算机上构建:

$ make
cc  -DDEBUG compress_image_test.c -o compress_image_test -Wall -ljpeg -ljasper -lm -lcheck
/usr/local/lib/libjasper.a(jpg_dec.o): In function `jpg_decode':
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_dec.c:158: undefined reference to `jpeg_std_error'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_dec.c:159: undefined reference to `jpeg_CreateDecompress'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_dec.c:162: undefined reference to `jpeg_stdio_src'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_dec.c:165: undefined reference to `jpeg_read_header'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_dec.c:168: undefined reference to `jpeg_start_decompress'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_dec.c:190: undefined reference to `jpeg_read_scanlines'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_dec.c:197: undefined reference to `jpeg_finish_decompress'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_dec.c:200: undefined reference to `jpeg_destroy_decompress'
/usr/local/lib/libjasper.a(jpg_enc.o): In function `jpg_encode':
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:284: undefined reference to `jpeg_std_error'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:285: undefined reference to `jpeg_CreateCompress'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:288: undefined reference to `jpeg_stdio_dest'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:294: undefined reference to `jpeg_set_defaults'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:310: undefined reference to `jpeg_set_quality'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:314: undefined reference to `jpeg_default_colorspace'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:317: undefined reference to `jpeg_start_compress'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:324: undefined reference to `jpeg_write_scanlines'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:329: undefined reference to `jpeg_finish_compress'
/cots/jasper-1.900.1/src/libjasper/jpg/jpg_enc.c:330: undefined reference to `jpeg_destroy_compress'
collect2: ld returned 1 exit status
make: *** [compress_image_test] Error 1

两台机器都运行 Ubuntu 12.04。 JasPer 和 JPEG 库是从源代码构建的,而不是通过 apt-get 获得的。

在阅读了另一个堆栈交换帖子lib dependencies and their order 之后,我尝试更新生成文件以将-ljpeg 的顺序交换到-ljasper 之后。这行得通。

所以我的问题是,原来的订单在另一台机器上可以吗,基本上和我的一样,但是在我的机器上不行?

5 月 5 日更新:

这些是我可以在我的计算机上找到的相关库文件:

/usr/lib/i386-linux-gnu:

lrwxrwxrwx 1 root root     18 Jun 21  2012 libjasper.so.1 -> libjasper.so.1.0.0
-rw-r--r-- 1 root root 317148 Jan 11  2012 libjasper.so.1.0.0
lrwxrwxrwx 1 root root     16 Nov 22 07:42 libjpeg.so.8 -> libjpeg.so.8.0.2
-rw-r--r-- 1 root root 284436 Nov 22 07:42 libjpeg.so.8.0.2

/usr/local/lib:

-rw-r--r-- 1 root root 1361856 May  2 09:14 libjasper.a
-rwxr-xr-x 1 root root     757 May  2 09:14 libjasper.la
-rw-r--r-- 1 root root 1461672 May  2 09:15 libjpeg.a
-rwxr-xr-x 1 root root     918 May  2 09:15 libjpeg.la
lrwxrwxrwx 1 root root      16 May  2 09:15 libjpeg.so -> libjpeg.so.9.1.0
lrwxrwxrwx 1 root root      16 May  2 09:15 libjpeg.so.9 -> libjpeg.so.9.1.0
-rwxr-xr-x 1 root root  955739 May  2 09:15 libjpeg.so.9.1.0

以及与我同事计算机上存在的文件相同的文件:

/usr/lib/i386-linux-gnu:

lrwxrwxrwx 1 root root     18 Oct 29  2013 libjasper.so.1 -> libjasper.so.1.0.0
-rw-r--r-- 1 root root 317148 Jan 11  2012 libjasper.so.1.0.0
lrwxrwxrwx 1 root root     16 Nov 22 07:42 libjpeg.so.8 -> libjpeg.so.8.0.2
-rw-r--r-- 1 root root 284436 Nov 22 07:42 libjpeg.so.8.0.2

/usr/local/lib:

-rw-r--r-- 1 root root 1320124 Apr 24 16:01 libjasper.a
-rwxr-xr-x 1 root root     750 Apr 24 16:01 libjasper.la
-rw-r--r-- 1 root root 1462456 Apr 24 16:06 libjpeg.a
-rwxr-xr-x 1 root root     918 Apr 24 16:06 libjpeg.la
lrwxrwxrwx 1 root root      16 Apr 24 16:06 libjpeg.so -> libjpeg.so.9.1.0
lrwxrwxrwx 1 root root      16 Apr 24 16:06 libjpeg.so.9 -> libjpeg.so.9.1.0
-rwxr-xr-x 1 root root  955351 Apr 24 16:06 libjpeg.so.9.1.0

据我所知,两个系统上存在所有相同的文件和链接。

【问题讨论】:

    标签: c linker dependencies shared-libraries


    【解决方案1】:

    您可能正在链接静态库。

    对于动态库,整个库都包含在链接中,这将使其所有符号都可用于后面提到的对象,而对于静态库,只有那些满足当前未定义的归档成员符号被链接,库的其余部分被忽略。

    【讨论】:

    • 两台计算机上的 makefile 相同。是否有一些潜在的不同会导致人们以某种​​方式仅使用动态库?
    • 动态库是首选。如果动态库没有正确安装,会导致对静态库的回退。
    • 在构建和安装库时,我当然使用了标准的“configure / make / sudo make install”例程。除了将库移动到库文件夹(在本例中为 /usr/local/lib)之外,还有什么要安装的库吗?
    • libjpeg.so 符号链接是否存在?那是链接器实际使用的内容,它应该指向完全版本化的共享库。
    • 符号链接确实存在。
    【解决方案2】:

    动态库有两种可能:

    1. 如果您将LD_LIBRARY_PATH 设置为包含其中可以找到libjpeg.so 的路径,那么ld 将在发现libjasper.so 需要它时自动在这些路径中搜索libjpeg.so

    2. libjasper.so 可以使用 -rpath ld 选项构建。在这种情况下,ld 也会自动在该路径中搜索依赖库。

      可以通过readelf -d /path/to/libjasper.so查看libjasper.so中是否有rpath。

    【讨论】:

    • 当我使用我自己的计算机本地帐户登录同事的计算机时,我可以构建它。我的帐户没有将 LD_LIBRARY_PATH 设置为包含 libjpeg.so 的路径。
    • @BenjaminLeinweber 哦,还有另一种可能性。 libjasper.so 可能包含 RPATH,ld 也会自动在该路径中搜索依赖库。你可以通过readelf -d /path/to/libjasper.so查看。
    • 看起来 JasPer 本身不使用动态库。我看到的唯一文件是 /usr/local/lib/libjasper.a 和 /usr/local/lib/libjasper.la。我已经确认我的同事设置是一样的。
    • @BenjaminLeinweber 你检查过 JPEG 库吗?你们都使用动态版本吗?您还需要检查两台机器中的这两个libjasper.a是否需要相同的外部符号?
    • 我们都以相同的方式安装库,并且都使用相同的 Makefile。 make 命令列在问题的代码块中。 /usr/local/lib/ 中与 JasPer 和 JPEG 相关的所有文件都存在于两个系统上。我不知道如何明确告诉系统使用动态库而不是静态库,反之亦然。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-17
    • 1970-01-01
    • 2013-05-18
    • 2021-08-21
    • 1970-01-01
    • 2013-07-12
    • 2013-11-18
    相关资源
    最近更新 更多