5

My project tree looks something like that:

src/
include/
Makefile
lib/
   lib/3rdparylib/

I didn't code 3rdpartylib, but decided to embed its source code in my project packaging. I compile the software by doing the following steps:

$ cd lib/3rdpartylib/
$ make
$ ln -s 3rdpartylib.so.0 3rdpartylib.so

Then I compile each of my source files like this:

$ gcc -c src/file.c -I include -o file.o -l 3rdparylib -L lib/3rdpartylib -I lib/3rdpartylib/include

Then I link:

$ gcc file1.o file2.o -l3rdpartylib -L lib/3rdpartylib -o myapp

When I am on my main machine, it works perfectly. Today I tried to launch it on another machine. It compiled and linked without any problem. However when I tried to launch the application I got the following error message.

./myapp: error while loading shared libraries: 3rdpartylib.so.0: cannot open shared object file: No such file or directory

I tried doing the following:

export LD_LIBRARY_PATH=/path/to/3rdpartylib.so

It seems to work. But I understand that using LD_LIBRARY_PATH is a bad practice. It bothers me to have this variable set up every time I want to run my app.

What am I missing? Why does it work on my main machine (where LD_LIBRARY_PATH is not set to anything) and not on the other machine? Does it matter that the other machine is a virtual one?

If it is of any help, my main machine is a Debian box, and my "new" machine is a Sabayon (Gentoo), running in Virtualbox.

rahmu
  • 20,023

4 Answers4

4

What matters is what Linux distribution each machine uses, because they handle library paths differently. On the Gentoo (Sabayon) machine, if you want a third party library to be usable system-wide, you should:

  • Create a file under /etc/env.d/ that will contain the additional environment setup. The files are named using the scheme [0-9][0-9]somename - the two initial digits decide on the order in which they are used. A good practice requires that your custom settings are added (near) last, so 99 is a proper beginning, as long as it works. Getting to the point: Create a file named like

    /etc/env.d/99mythirdpartylib
    

    containing

    LDPATH=/path/to/your/library
    
  • To make the changes active without reboot, run as root:

    env-update && source /etc/profile
    

    (which will update the environment as well as run ldconfig).

Reference, if you'd like one.

1

If you don't want to set a global library search path for your whole system with the /etc/env.d approach, you can either:

Just set the LD_LIBRARY_PATH to the PATH of your library (you did set it to the library itself, that won't work), the same which you set with the -L parameter to gcc e.g.

export LD_LIBRARY_PATH="$PROJ/lib/3rdpartylib/:$LD_LIBRARY_PATH"

(the last part is for preserving the variable if it was already set, which it shouldn't be normally). This will only work in you current shell and you will have to set it again everytime.

Or you link using a 'static' library search paths like this:

gcc file1.o file2.o -L./lib/3rdpartylib -Wl,-rpath=./lib/3rdpartylib  -l3rdpartylib  -o myapp

-Wl specifies commmand line arguments that will not be processed by gcc but instead be passed to the linker. Since the library search path will be written into the binary, this will work even on different machines (provided the library exists)

PS: Since you're just talking about the case where you're developing a project, I think this temporary way is more appropriate than putting it in system-wide configuration files.

moschlar
  • 111
0

The line:

$ gcc file1.o file2.o -l3rdpartylib -L lib/3rdpartylib -o myapp

searches for a file called lib3rdpartylib.so in your library path, which doesn't even include lib/3rdpartylib! If you look at the gcc man page, it states that when specifying a library path with -L it must come before the -l flags, or it will not be searched. Really, the simplest solution is to just link to the library itself:

$ gcc file1.o file2.o lib/3rdpartylib/3rdpartylib.so -o myapp

That way, the library will be searched for in the library paths and dynamically loaded when myapp runs.

If you want to check it, just do an strace -eopen ./myapp once it's installed and look at where it tries to load the library from.

amphetamachine
  • 5,517
  • 2
  • 35
  • 43
-1

You have to tell your system where to look for libraries. This job is done by /etc/ld.so.cache. You can add libraries or whole directories in /etc/ld.so.conf.

You can rebuild the cache by doing:

# /sbin/ldconfig -v
Mat
  • 52,586
fab
  • 1
  • On Gentoo this is not the way to do it: the top line of /etc/ld.so.conf proves it vividly, saying *"ld.so.conf autogenerated by env-update; make all changes to contents of /etc/env.d directory"* – rozcietrzewiacz Nov 24 '11 at 19:02
  • ...And /etc/env.d is sourced on each boot, so you'd loose all your changes. – rozcietrzewiacz Nov 24 '11 at 19:04
  • Ok I don't know Gentoo, env-update will do exactly what I say : env-update will also extract the information from the LDPATH variable and use that to create /etc/ld.so.conf. After this, it will run ldconfig to recreate the /etc/ld.so.cache. So your answer is better ;-) – fab Nov 24 '11 at 20:33