How to get it REALLY right with LD_LIBRARY_PATH and linking? - c++

I'm repeatedly experiencing problems with libraries which are not found.
In my bashrc I have:
LD_LIBRARY_PATH=
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib1
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib2
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib3
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH
These paths contain ALL folders from where I link libraries into my program with -L/lib1 -l1a -L/lib2 -l2a -L/lib3 -l3a.
Now I start my program standalone:
./program
Fine!
Then I start it with mpiexec from mpich:
/mpich/intel/bin/mpiexec -np 2 ./solvertest1
Fine!
BUT THEN I start it with gdb enabled:
/mpich/intel/bin/mpiexec -np 2 gdb ./solvertest1
Problem, libraries are not found:
Starting program: /my/program
/my/program: error while loading shared libraries: libirng.so: cannot open shared object file: No such file or directory
I suspect that there's something wrong when the LD_LIBRARY_PATH should be propagated through all the subprocesses and shells those scripts and programs produce... What do I have to do to let every subprocess (and whatever else will be started) know where those libraries are?

Store the library path in the DT_RPATH tag of your executable when linking
-Wl,rpath=/lib1 -Wl,rpath=/lib2 -Wl,rpath=/lib3
that way you don't need to mess with LD_LIBRARY_PATH and shell initialization.

Since the program is dependent on having the right environment variables set to run, and mpiexec isn't giving it the env it needs, try something like these from the mpiexec docs:
-x , --envall
Export all environment variables to all processes.
-E , --env name value
Export the variable name with the content value.

Related

How to specify .so path to use with GDB whan analysing dump file?

I have a crash dump that I want to analyse with GDB on different computer. Crashed application uses several shared libraries (*.so files). I want GDB to load symbols from some of them but I can't put all of them in the original path.
Adding LD_LIBRARY_PATH to the environment doesn't help when working with dumps. When I type info shared it shows full (non-relative) paths:
(gdb) info shared
From To Syms Read Shared Object Library
0x00007fad4fb7f220 0x00007fad4fb80179 Yes /lib/x86_64-linux-gnu/libdl.so.2
...
No /opt/app/libXXX.so
...
How to specify different path for the example libXXX.so (from gdb command line or command prompt)?
The set solib-search-path option is for that purpose. Documentation says it is ment for using with gdbserver but also works with dump analysis. By default, it is set to ., so the directory that gdb is run from.
BUT: for some reason it doesn't work out of the box (at least with gdb 10.2). I don't know the reason, but I know a workaround: just type set solib-search-path . as a first command after entering gdb prompt. The output is following for me:
(gdb) set solib-search-path .
Reading symbols from /home/example/path/libXXX.so...
Of course one can type any path she want instead of ..

Can link to libboost but cannot execute the executable [duplicate]

I wrote a shared object, say libsd.so, and I put libsd.so and its header file sd.h in ~/lib.
Here is another program using libsd.so, say test.c, then compile it like this:
$ gcc -o test test.c -I~/lib -L~/lib -lsd
Then I run test like this:
$ ./test
./test_sd: error while loading shared libraries: libsd.so: cannot open shared object file: No such file or directory
So I set export LD_LIBRARY_PATH=., then it works. But if I unset LD_LIBRARY_PATH and put LD_LIBRARY_PATH=~/lib in my ~/.bashrc, then source ~/.bashrc, again it doesn't work for ./test, WHY?
export LD_LIBRARY_PATH=~/lib is difference from putting LD_LIBRARY_PATH=~/lib in ~/.bashrc?
Without the export your declared LD_LIBRARY_PATH is only valid in the script (.bashrc).
With the export it should work, but it is usually not a good idea to set your LD_LIBRARY_PATH like this.
If you don't want to install your library in the system path (e.g. /usr/lib) you should probably use a script that sets LD_LIBARAY_PATH locally and starts your application.
Try $HOME/lib instead of ~/lib - it should be the same but I've seen cases where ~ wasn't expanded properly when used in an variable assignment.
To check, try echo $LD_LIBRARY_PATH which gives you the current value.
Re export: If you omit the export, then the variable is only known to the current shell process and will not be exported to child processes. So if you omit it, echo $LD_LIBRARY_PATH will get the value because the variable is expanded by the shell before the echo command/builtin has a chance to do anything. But ./test won't see it because it's not exported to the new subprocess.

Unable to load shared library : libxerces.so

While running the application developed by other person, getting the following error
./appln: error while loading shared libraries: libxerces-c.so.28: cannot open shared object file: No such file or directory
And if I run ldd command:
# ldd appln
linux-gate.so.1 => (0x00e20000)
libdl.so.2 => /lib/libdl.so.2 (0x00a61000)
libxerces-c.so.28 => not found
I already have that libxerces-c.so.28 file in current folder. Please help me how to resolve that error
You need to put libxerces-c.so somewhere in the library path. Probably current folder is not searched for libraries. Try putting it in /usr/local/lib
Evidently "the current folder" isn't in the run time search path used by your executable. I'm assuming that you are on linux (linux-gate.so.1).
You need to ensure that "the current" directory is under the search path. You can do this at link time by using the -rpath option to the linker (-R is also accepted) or -Wl,-rpath,<dir> if you are invoking the linker through the compiler front end. This embeds a search path to be used at run time into your program.
Consider how you want the program to be installed, though. There's no point in adding a path that is specific to your development environment. You might want to consider using $ORIGIN or a $ORIGIN relative path which tells the run time linker to look for shared objects in the location containing (or relative to) the executable. You should always avoid adding . to the run time search path; your program shouldn't behave differently depending on the current directory of the process which invokes it.
As a temporary measure you can set the environment variable LD_LIBRARY_PATH to override the embedded and system search paths but it is normally a bad idea to rely on LD_LIBRARY_PATH overrides for a final installation.
By default .so files are NOT being searched in the current folder (they should be in /usr/lib, etc).
To add the current directory for .so lookup use:
LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH ./appln
When adding new "local system" libraries (e.g. in /usr/local/lib/) you better add that directory (/usr/local/lib/) once in your /etc/ld.so.conf and you should run ldconfig to update the linker cache (every time you add something inside /usr/local/lib/)
See ldconfig(8), ld.so(8), ldd(1), dlopen(3)
If you want your own libraries, set LD_LIBRARY_PATH to a directory containing them (e.g. $HOME/lib/ and to standard directories, e.g.
export LD_LIBRARY_PATH=$HOME/lib:/usr/lib:/usr/local/lib
in your ~/.bashrc (but I dislike that confusing practice, and prefer to manage my /usr/local/lib/).
You could also use some -Wl,-rpath argument but I really dislike that also.
Read also Program Library HowTo and Drepper's paper: How To Write Shared Libraries

GDB "cannot open shared object file" Issue

I've already read gdb says "cannot open shared object file" and gdb can not open shared object file and followed the instructions.
I have a binary which is linked to a shared library file (/zzz/yyy/xxx.so). After I set LD_LIBRARY_PATH to /zzz/yyy/ and run the binary without GDB, it executes very well.
However, when I was trying to use GDB to debug this binary, GDB says:
error while loading shared libraries: xxx.so: cannot open shared object file: No such file or directory
I already have (set in .gdbinit):
(gdb)show env LD_LIBRARY_PATH
LD_LIBRARY_PATH = "/zzz/yyy/"
and
(gdb) show solib-search-path
The search path for loading non-absolute shared library symbol files is "/zzz/yyy/".
and in my system:
% printenv LD_LIBRARY_PATH
/zzz/yyy
What's the other possible reasons why GDB still can't find this shared library?
However, when I was trying to use GDB to debug this binary, GDB says: error while loading shared libraries: xxx.so: cannot open shared object file: No such file or directory
You are mistaken: it's not GDB that says that, it's the dynamic loader. GDB itself doesn't care what LD_LIBRARY_PATH is set to, it simply runs your program. But your program can not run.
The most common cause: you are re-setting your LD_LIBRARY_PATH in your ~/.cshrc, and GDB runs your program in a separate shell, and that shell reads your .cshrc, so your program executes with incorrect environment.
The fix is to make .cshrc not set LD_LIBRARY_PATH for non-interactive shells. See e.g. this answer.

Linux - SO file not found

I have a program which requires liblog4cpp installed to run.
Now, I want the program to run on another machine without liblog4cpp. So I just find the log4cpp.so and move it to the same directory of my program. But at running error reported:
error while loading shared libraries: liblog4cpp.so.4: cannot open
shared object file: No such file or directory
Am I doing it right? How can I tell the program to find the SO file just beside it?
In addition to what others are suggesting, consider adding the file to the dynamic linker's cache. You can do it like this:
ldconfig -l /path/to/lib/liblog4.so.4
To add it to the loader's cache use the following command: ldconfig
Then in order to verify that it was correctly added, run this:
ldconfig -v | grep liblog
Check your LD_LIBRARY_PATH environment variable... One of the directories on the path should point to the location of your log4cpp.so file; also the linux command ldd is handy for determining which shared object libraries are being used in your executable. The syntax is ldd <executable>.
assuming that the path where the .so file/s is available is /path you can also avoid to export an environment variable and just use
LD_LIBRARY_PATH=/path ./myProgram
beware the fact that if you do:
export LD_LIBRARY_PATH=/path
you are resetting LD_LIBRARY_PATH to a single value /path and losing anything you added before to this environment variable. If you want to add a value without losing the previous ones
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path
export LD_LIBRARY_PATH to the path of the library. This env variable works much like the PATH variable. It can contain multiple paths separated by :.
In the rc script from where you are launching your program, you should set the LD_LIBRARAY_PATH before launching the application. Remember, the .so are the shared libraries, it is required at the run time to link. Thus, it should be available in the standard path like /usr/lib before launching.
In case it is not copied in the standard path like /usr/lib then specify the path by using the following.
export LD_LIBRARY_PATH=<new_path_of_so>:$(LD_LIBRARY_PATH)
Ideally, I would have placed this .so in the standard path like /usr/lib. If it is installed in the standard path, then there is no need to set the above path. Remember, to make your program better, put the new path in ldconfig.conf.
You can debug such errors by using the following.
$strace <binary_name>
to know the so dependencies
$ldd <binary_name>
For further, check the below link.
http://www.tune2wizard.com/sharedobject-crash/
After adding shared objects (or shared libraries lib*.so*, or such symbolic links) to system directories like /usr/lib or /lib known to the dynamic linker ld-linux.so(8) (or ld.so) you need to run ldconfig(8)
You could also add them to /usr/local/lib/ but then be sure that /etc/ld.so.conf (or some file /etc/ld.so.conf.d/*.conf) .mentions that directory (and run ldconfig after changing it)