Cannot find shared library even with LD_LIBRARY_PATH set, while setting ld.so.conf works - linux

The program fails to find a shared library even with the path of the library included in $LD_LIBRARY_PATH (also exported correctly). However, after I add the path to /etc/ld.so.conf and then execute ldconfig, the program runs without error.
Why does this happen?

Related

how to search shared library when running an executable?

I have an excutable and a shared library in same directory, the executable running well, however, after moving the shared library to other pos, I can not run the executable showing can not find libxxx.so
I want to know why it happens?
You can move the library to some standard library path. It is defined in /etc/ld.so.conf. The loader will only find libraries defined in there. In the other hand, you can also use LD_LIBRARY_PATH env variable to put your shared library path. It makes sure the path is searched first

C++ executable fails to link to shared library after scp

So I am working on a project that is intended to run on a remote server. I develop the program on a local pc, compile it, then upload it to the remote server. Both the local pc and the remote server are run on CentOS 7.7.
The program is developed using the CLion IDE, configured with CMake. The program depends a few shared libraries, which are supposed to link to the executable according to what I wrote in CMake. At my local PC, I can compile and run the program perfectly. However, after I scp the whole directory of the project to the remote server, the executable fails to run. It cannot find any of the ".so" files, according to what ldd says.
This is my CMakeList.txt, with every path being relative path, instead of absolute path.
cmake_minimum_required(VERSION 3.15)
project(YS_Test)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_PATH_ src)
file(GLOB SOURCE_FILES_ ${SOURCE_PATH_}/*.*)
set(PROJECT_LIBS_ libTapQuoteAPI.so libTapTradeAPI.so libTapDataCollectAPI.so)
include_directories(api/include)
link_directories(api/lib/linux)
add_executable(YS_Test ${SOURCE_FILES_})
target_link_libraries(YS_Test ${PROJECT_LIBS_})
Please do not tell me to set LD_LIBRARY_PATH to fix my issue. The program worked fine on my local pc without LD_LIBRARY_PATH, so I expect it to run on the remote server without LD_LIBRARY_PATH. I would like to know what is really going on here, instead of a work around. Thanks!
If I understand your problem correctly, you want to ship your compiled YS_Test program along with some dependencies and have it run on a remote server. By default an executable will only look in the directories configured in /etc/ld.so, which will not include the deploy path.
Note: Typically you do not deploy your entire build directory but only the compiled artifacts and dependencies. For this answer I will assume you deploy the binary and its dependencies to the same directory.
You have two options:
Require users of your program to set LD_LIBRARY_PATH, either by themselves or by a wrapper script. This variable will instruct the dynamic linker to look in the specified directories as well. Even if you do not like this solution, it is by far the most common approach.
Add -Wl,-rpath='$ORIGIN' to your linker options. This will add a DT_RUNPATH attribute to the executable's dynamic section. As you are using CMake you can also set this using BUILD_RPATH and/or INSTALL_RPATH target properties.
The ld.so manpage describes this attribute as follows:
If a shared object dependency does not contain a slash, then it is
searched for in the following order:
...
Using the directories specified in the DT_RUNPATH dynamic section
attribute of the binary if present.
The $ORIGIN part expands to the directory containing the program or shared
object.
If you really insist on shipping your build directory (eg during development), you can take a look at the CMake BUILD_RPATH_USE_ORIGIN property (and its usual global counterpart CMAKE_BUILD_RPATH_USE_ORIGIN), this will embed relative paths into binaries instead of absolute paths.
As you don't want a workaround (#Botje has given you two already), I will try an explanation instead. In your development machine, if you use this command:
ldd YS_Test
You will see all the shared libraries used by your program, with their corresponding paths. The libTapQuoteAPI.so libTapTradeAPI.so libTapDataCollectAPI.so are found at your 'api/lib/linux' directory, but resolved with full absolute paths. If you do the same at your server, some shared objects can't be resolved because they aren't at the same location.
If you use one of these commands (not sure which are available in Centos):
chrpath --list YS_Test
or
patchelf --print-rpath YS_Test
You will see the RPATH or RUNPATH tags embedded in your program. This is the path used by the Linux linker to locate dependencies that are outside the standard ld locations. You may find extended explanations on Internet about this, like this one or the Wikipedia article.
Breaking my promise, I give you a third workaround: use patchelf or chrpath at your server after scp to change the embedded RPATH tag, pointing it relative to $ORIGIN (which represents the program location).

Error while loading shared library : librun.so

I have a compiled script (it's some utility) and the source code of which is unavailable. As soon as I run the script this error shows up:
error while loading shared libraries: librun.so: cannot open shared object file: No such file or directory
I have faced these kind of errors in past which had different solutions. I tried all as per my knowledge and..
librun.so is there in lib folder of my application
It is symbolic link and pointing to correct version
librun.so is available in path variable
changed .profile to look for the required library
changed permissions and checked
"which librun.so" is also returning the presence of that library
still this error shows up.
What can be the reason for this problem?
The dynamic linker is unable to find librun.so during runtime linking of shared libraries. Try adding the path of directory containing librun.so to the LD_LIBRARY_PATH environment variable when starting the application script.

Looking for missing shared library

On a Linux system, I am trying to run a Fortran program that makes use of some shared libraries (netCDF libs, if that makes a difference). Before I run, I set LD_LIBRARY_PATH so that it points to the location of my libraries. Then I run the executable and I quickly get the error
../my_program: error while loading shared libraries: libnetcdff.so.5: cannot open shared object file: No such file or directory
Now, I double check the value of LD_LIBRARY_PATH, and then cd to it and find plain as day
$ ls *ff*
$ libnetcdff.a libnetcdff.la libnetcdff.so libnetcdff.so.0 libnetcdff.so.0.0.0
So the libnetcdff is absolutely present.
Could anyone point me to the problem?
The one thing that has occurred to me is that the executable seems to want to find libnetcdff.so.5, while the library that is present is actually libnetcdff.so.0. Is that the problem? If so, is there a way to convince the executable to not insist on "5"? Alternatively, would a link from libnetcdff.so.0 to libnetcdff.so.5 solve the problem? (I don't have permissions in the directory, BTW, which is why I haven't tried that yet.)
Environment info: CentOS machine, code compiled with gfortran. And yes, when I compiled, my -L flags were pointing to the same directory that LD_LIBRARY_PATH points to.
Thanks.
A library link should work. Since you mention that you do not have root/sudo access, what you can do is link in a file you do have access in:
ln -s /path/to/libnetcdff.so.0 /path/you/have/access/to/libnetcdff.so.5
And then add in the /path/you/have/access/to/ in your LD_LIBRARY_PATH.

gcc: linked libraries in /usr/local/lib are not found, but /etc/ld/so.conf.d/libc.conf lists it?

I've got a problem with shared libraries and gcc. At first I couldn't run my compiled program because I was getting the following error: gcc error while loading shared libraries.
I did some searching and found that this is because the shared library cannot be found. However I had already identified that the shared library is in /usr/local/lib, which AFAICT is a commonly used directory for shared libraries and should work from the get go.
I read that you can set LD_LIBRARY_PATH, which worked for me. However I do not wish to set this each time I want to run my program.
Further searching suggested editing ld.so.conf. When I looked in this it had the following:
include /etc/ld.so.conf.d/*.conf
Looking in the ld.so.conf.d directory shows me a range of files, including libc.conf. Inside this file is the following:
/usr/local/lib
So my question is, why do I need to manually set LD_LIBRARY_PATH when the ld.so.conf appears to use the libc.conf which includes /usr/local/lib?
Is there something that I'm missing here that must be configured first? Is there an option at compile time that I'm missing?
I should note that to compile, I had to specify the path to the library, I don't know if this is a symptom of my problem or normal behaviour.
I should also note that this is a concern for me for when I deploy my software on other systems. I would have thought that I should be able to put the .so in the appropriate place and install my program without messing with ld.so.conf.
I hope this is the proper forum for this question, I read the FAQ and I think it's ok.
Cheers.
You should run ldconfig (as root) after every change of the directories configured via /etc/ld.so.conf or under /etc/ld.so.conf.d/, in particular in your case after every update inside /usr/local/lib (e.g. after every addition or update of some shared libraries there).

Resources