Benjamin Leinweber
Benjamin Leinweber

Reputation: 2944

Why does C library link order only matter on some systems?

My group developing a program which uses the JasPer library which depends on a JPEG library. My co-worker created a Makefile which listed the -ljpeg before -ljasper in the build rule. This worked fine on my co-worker's computer but would not build on mine:

$ 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

Both machines are running Ubuntu 12.04. The JasPer and JPEG libraries were built from source, not obtained through apt-get.

After reading another stack exchange post, lib dependencies and their order, I tried updating the makefile to swap the order of -ljpeg to after -ljasper. This worked.

So my question is, was the original order ok on another machine, which is basically equivalent to mine, but it did not work on my machine?

May 5th Update:

These are the relevant library files that I can find on my computer:

/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

And the same files as they exist on my co-workers computer:

/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

As far as I can see, all of the same files and links exist on the two systems.

Upvotes: 3

Views: 455

Answers (2)

Lee Duhem
Lee Duhem

Reputation: 15121

There is two possibilities for dynamic libraries:

  1. If you set LD_LIBRARY_PATH to include path that in it libjpeg.so could be found, then ld will search in these paths for libjpeg.so automatically when it find out that libjasper.so needs it.

  2. That libjasper.so may be built with a -rpath ld option. In this case, ld also will search in that path for dependent libraries automatically.

    You can find out whether there is a rpath in libjasper.so by readelf -d /path/to/libjasper.so.

Upvotes: 1

Simon Richter
Simon Richter

Reputation: 29586

You are probably linking against a static library.

With dynamic libraries, the whole library is included in the link, which will make all of its symbols available to objects mentioned later, while for a static library, only those archive members that satisfy currently undefined symbols are linked, and the rest of the library ignored.

Upvotes: 4

Related Questions