shared library problems on linux - linux

I'm trying to compile/link a very old piece of software on a linux system and I can't for some reason link with a shared library that's installed on my system.
I get the following error from the linker:
/usr/bin/ld: cannot find -lXaw
However, the lib itself is installed. If I run
ldconfig -v | grep libXaw
I get (among other things) this hit:
libXaw.so.7 -> libXaw7.so.7.0.0
The library and the links to it are in /usr/lib btw. So nothing special.
So the library is there and ldconfig finds it. What could ld cause ld from not finding the library during link-time? As you may have already guessed I'm quite new to the shared library stuff.
Any ideas?

The linker may be looking, literally, for "libXaw.so". Is that in /usr/lib? If not, you could try adding it as another soft link from libXaw7.so.7.0.0.

The reason for the symlink btw is to select the default version to link against in the case of multiple versions, keep in mind the name of the library is integrated into the binary. (which you can see with ldd).

Are the -L library directories being overridden, and it's not looking in /usr/lib?

To link it, you need the .a file, NOT the .so file, which is the runtime library. The shared object is only useful to a program already linked against the non-shared parts of a library. This is typically distributed in a ".a" file.

Related

Shared library name in executable is different than the filename

A cleaned up version of my compile command looks like gcc -o semantic_seg -Wl,-rpath,... -l:libnvrtc-5e8a26c9.so.10.1 ... and I have a dynamic library file named exactly libnvrtc-5e8a26c9.so.10.1 in the directory specified by the -rpath flag. The command succeeds.
When I go to run my program, it says semantic_seg: error while loading shared libraries: libnvrtc.so.10.1: cannot open shared object file: No such file or directory and when I do ldd it shows libnvrtc.so.10.1 => not found.
So the problem looks like the name of the shared library in the executable is not the same as the filename. Could that be true? Did the 5e8a26c9 part of the name somehow get stripped off?
Update: Creating a symbolic link libnvrtc-5e8a26c9.so.10.1 -> libnvrtc.so.10.1 allows the executable to run. But I'm still not sure the mechanism that causes this name modification to happen. It seems a bit magic.
Could that be true?
This is often true.
On ELF systems, the linker uses SONAME of the library (if it has one) and not its filename to record a runtime dependency.
Running readelf -d libnvrtc-5e8a26c9.so.10.1 | grep SONAME will likely show that in fact that library does have SONAME, and the value of SONAME is libnvrtc.so.10.1.
This used to be very convenient for external library versioning.
Update:
it allows you to link against a library which will be different than the one which will used at run time, but why would I ever want that?
Like I said, it's useful for external library versioning and ABI evolution.
Suppose you ship version 1.0 of libfoo.so. You provide libfoo.so as a symlink to libfoo.so.1, and you use libfoo.so.1 as SONAME.
Any program that links with gcc main.c -lfoo (note: no funny -l:libfoo.so.1 syntax required) will record libfoo.so.1 as its external dependency, and will use that name at runtime.
Time passes, and you are ready to ship version 2, which is not ABI-compatible.
You don't want to cause all your end-users to change their link line, and you don't want to break any existing binaries.
With the SONAME, this is trivial: new package will include libfoo.so.2 with SONAME of libfoo.so.2, and a symlink libfoo.so now pointing to libfoo.so.2.
Voila: both requirements are achieved: existing binaries continue to use libfoo.so.1, newly-linked binaries use libfoo.so.2, no Makefile changes required.

Shared Library on Linux is not found

I have built some shared libraries on Ubuntu Linux 16.0.2 from source.
They are 64-bit libs.
I manually copied them to /usr/local/lib.
I verified that the /usr/local/lib path is indeed in one of the .conf files that ld.so.conf includes.
I then ran: sudo ldconfig to update the cache.
But then when I try to run my executable which tries to dynamically load one of the .so files that I previously copied into /usr/local/lib using dlopen, it fails.
In my code, I have:
dlopen ("foobar.so", RTLD_LAZY);
Can anybody tell me what I am doing wrong?
The dynamic linker normally doesn't access the paths recursively included from /etc/ld.so.conf directly, but it uses a cache.
You can update the cache with
sudo ldconfig
See ldconfig(8) for more details.
for dlopen to work, there's no directory list of places to find the shared object. So doing dlopen("somefile", ...); probably won't work.
You don't need to use any path or to put the shared object (or to comply with naming conventions) to use a shared object via dlopen(3). That's only a requirement of the dynamic linker that loads and links all the shared libraries at launch time: linux-vdso.so.1 (in 64bit)
To test, just put the shared in your local dir and try to open it with it's basename, like you post.
For a system library, there are more requirements, like defining a soname for the library, which is used by the loader to load the library and to construct the cache database index, so if you have no idea of what I'm talking about, you will not be able to use automatic loading procedure. If you want to see if an executable file has all the libraries it needs and where the loader finds them out, just run ldd(1) with the executable as argument, and you'll se the dependencies for automatic loading and how the dynamic linker resolves the paths.

Unable to link shared libraries not under the system library directories on Ubuntu 12.04

I created a shared library, libsslab_core.so.1.0.0 using gcc with proper options. I am pretty sure that the shared library works because I already linked it to another source code (I explicitly tells a compiler, gcc, the location of the library using -l option of the compiler).
After testing the library works, I tried to integrate the library into my Linux machine. I went to the /etc/ld.so.conf.d/ and added a file, sslab.conf. In the file I just typed the absolute path of the library, /opt/lib/sslab. Next, I executed ldconfig as a root to update the cache file of ldconfig. And I checked if the system finds the newly added library by typing ldconfig -p | grep libsslab. My Linux machine found the library, so I thought everything is finished.
However, when I try to compile a source code using the library, it gives me the following error:
/usr/bin/ld: cannot find -lsslab_core
When I move the library to /usr/local/lib, update the content of sslab.conf, and execute ldconfig as a root. I can use the shared library without any problems.
Do you have any ideas about the problem that I've come across on Ubuntu 12.04?
For your information, I refer to a document in TLDP to generate my own shared library. Here is the link: http://www.tldp.org/HOWTO/Program-Library-HOWTO/

wrong soname of shared library loaded at runtime Ubuntu

I'm using eclipse cdt to compile and run C++ application.
My_main_program needs specifically libjpeg.so.62.
My Ubuntu system previously have libjpeg.so.9 at /usr/local/lib/. I happened to compiled and run using libjpeg.so.9 before run-time compatibility errors was raised.
Then I deleted all libjpeg.* and installed libjpeg.la, libjpeg.so, libjpeg.so.62 and libjpeg.so.62.0.0 from source. Then I run ldconfig.
I can build the project. The problem is the dynamic linker keeps searching for libjpeg.so.9 and throwing
'error while loading shared libraries: libjpeg.so.9: cannot open shared object file: No such file or directory'
at run-time.
This problem is killing me.
I have checked that the symlink of libjpeg.so is correct.
Please help!
I can build the project. The problem is the dynamic linker keeps searching for libjpeg.so.9 and throwing
'error while loading shared libraries: libjpeg.so.9: ... No such file ...
You need to understand a couple of things:
A shared library may have SONAME dynamic tag (visible with readelf -d foo.so | grep SONAME).
If an executable is linked against such a library, the SONAME is recorded as a NEEDED dynamic tag (in the executable), regardless of what the library itself is called. That is, you can name the library foo.so, foo.so.1234, or anything else. IF the library has SONAME of libbar.so.7, then the executable will require libbar.so.7, no matter what [1].
On to your problem. Your executable fails to load libjpeg.so.9, therefor we conclude that it is being linked (at build time) with a shared library which has SONAME: libjpeg.so.9.
I deleted all libjpeg.* and installed libjpeg.so.62
You must not have deleted the libjpeg.so that is used at executable build time (which is somewhere other than /usr/local/lib). That library still has SONAME: libjpeg.so.9, and is causing you grief.
You can find out which libraries are being used at link time by passing -Wl,-t flag on the link line.
[1] Not strictly true: if the executable doesn't need any symbols from foo.so, and if --as-needed linker option is in effect, then NEEDED: libbar.so.7 will not be recorded after all.
Update:
I have also check ldd executable and it returns libjpeg.so.62
This means that the executable that you run ldd on is correct, but the executable that actually run is not, and they must be different executables.
Update 2:
You're right. ldd executable shows both libjpeg.so.62 and libjpeg.so.9 are included
Actually, no, I wasn't. But I will be right this time.
What's happening is that your executable correctly records NEEDED: libjpeg.so.62 (you can verify this with the following command: readelf -d /path/to/exe | grep 'NEEDED.*libjpeg').
But you also have some other shared library (one of the ones listed in ldd output), which has not been rebuilt, and still has a dependency on libjpeg.so.9.
You can find that library by running readelf -d /path/to/libXXX.so | grep 'NEEDED.*libjpeg\.so\.9' on all libraries listed in ldd output.
Once you find it, you'll have to rebuild it so it also depends on libjpeg.so.62.

using older version of a shared linux library while compiling C

I am trying to use libfann version 2.0.1 instead of the newest version 2.2.0, but could not figure out how to do so. Any thoughts on how to do that?
normally that works perfectly:
gcc fann_calculator.c -o run_fann_calculator -lfann -lm
where fann_calculator.c contains a program that calls a neural network.
Thanks
It depends upon where the two libraries sit. If they are installed in the same directory (e.g. both installed in /usr/lib/) you'll probably get the youngest one.
I suggest to carefully read the ld.so(8) and ldd(1) man pages. You certainly can trace what library is loaded (with e.g. the LD_DEBUG envirnonment variable). Don't forget to re-run ldconfig appropriately after library installation.
You could also play some LD_LIBRARY_PATH trick; for instance, set it to $HOME/lib:/usr/lib and install appropriate symlinks in your $HOME/lib/ to the precise library you want. For instance, you might do
ln -s /usr/lib/libfann.so.2.0.1 $HOME/lib/libfann.so.2
export LD_LIBRARY_PATH=$HOME/lib:/usr/lib:/lib
then check with ldd run_fann_calculator that you get the expected [version of the] libfann library.
Don't forget to read the Program Library Howto. You might want to pass appropriate flags to ld such as -rpath. You may need to pass them using gcc, perhaps with Gcc Link Options such as -Wl

Resources