Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The difference between '-lfoo' and '/path/to/libfoo.so' when linking

Tags:

gcc

linker

ld

It seems that you can pass the /path/to/libfoo.so as input file to gcc and program will be linked correctly with it, just as when using -lfoo option in combination with -L/path/to.

In case I know the full path of needed version of library, what is the difference?

like image 818
Michael Pankov Avatar asked Oct 21 '25 19:10

Michael Pankov


1 Answers

If you're certain you know the right path to the right library, and the library is a static archive, /path/to/libfoo.a, then there's no difference, but for a shared library it makes a difference.

If you run ldd and/or readelf on your executable you'll see the the linker has added a dependency to the library at that specific location, e.g. here's a link using -L and -l:

$ g++ main.cc -lfoo -L.
$ readelf -d ./a.out | fgrep libfoo
 0x0000000000000001 (NEEDED)             Shared library: [libfoo.so]
$ ldd ./a.out
        linux-vdso.so.1 =>  (0x00007fff9b1fa000)
        libfoo.so => not found
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x0000003ebe200000)
        libm.so.6 => /lib64/libm.so.6 (0x0000003ebc200000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003ebd200000)
        libc.so.6 => /lib64/libc.so.6 (0x0000003ebbe00000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003ebba00000)

Note that the dependency is just libfoo.so (and is not found because . isn't in my shared library search path, ignore that for now.)

Here's the same test, but using the pathname of the library:

$ g++ main.cc /dev/shm/libfoo.so
$ readelf -d ./a.out | fgrep libfoo
 0x0000000000000001 (NEEDED)             Shared library: [/dev/shm/libfoo.so]
$ ldd ./a.out
        linux-vdso.so.1 =>  (0x00007fff963f4000)
        /dev/shm/libfoo.so (0x00007fad91c48000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x0000003ebe200000)
        libm.so.6 => /lib64/libm.so.6 (0x0000003ebc200000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003ebd200000)
        libc.so.6 => /lib64/libc.so.6 (0x0000003ebbe00000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003ebba00000)

Notice that now the dependency is /dev/shm/libfoo.so.

This means that your program will fail to find the library at run-time if it isn't installed in the same location on your development machine and the machine where you plan to run it.

However, this only applies if the library does not have a SONAME, if I relink the library specifying a soname (with the linker's -h option) and then relink my executable, the dependency uses the library's soname, even if I specify a full path:

$ g++ -shared foo.cc -o libfoo.so -Wl,-h,libfoo.so
$ readelf -d libfoo.so | fgrep libfoo
 0x000000000000000e (SONAME)             Library soname: [libfoo.so]
$ g++ main.cc /dev/shm/libfoo.so
$ readelf -d ./a.out | fgrep libfoo
 0x0000000000000001 (NEEDED)             Shared library: [libfoo.so]

To really demonstrate the dependency uses the soname, we can give it a soname that doesn't match the filename at all:

$ g++ -shared foo.cc -o libfoo.so -Wl,-h,libbar.so
$ readelf -d libfoo.so | fgrep SONAME
 0x000000000000000e (SONAME)             Library soname: [libbar.so]
$ g++ main.cc /dev/shm/libfoo.so
$ readelf -d ./a.out | fgrep libbar
 0x0000000000000001 (NEEDED)             Shared library: [libbar.so]
like image 55
Jonathan Wakely Avatar answered Oct 26 '25 01:10

Jonathan Wakely



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!