Linux: executable cannot find shared library
I have compiled casablanca and have put -l:/~/path/to/lib/libcasablanca.so in my CMakeList.txt . I have build my application and I have got no errors. But when I run the executable it says:
./myproj: error while loading shared libraries: libcasablanca.so: cannot open shared object file: No such file or directory
I have done it on another computer and it seems to work fine. Does anyone know what is the problem? How to fix this? I have no administrator access to this machine.
1 Answer 1
This is very simple: your library is not in the default system path from them the shared libraries are imported. During the compilation, the compile scripts solved these problems. In runtime, you have the LD_PRELOAD or LD_LIBRARY_PATH environment variables.
For example: an export LD_LIBRARY_PATH=/home/darkside/wunderprog/lib will extend the directoried searched for your libraries with the named directory. If there is your libcasablanca.so , you will get what you want.
Normally I use a /home//lib directory in my useronly accounts and set LD_LIBRARY_PATH from .profile .
If I do export LD_LIBRARY_PATH=/~/path/to/lib , does it removes the values existent in the variable? Or there is nothing in it?
@thedarksideofthemoon Yes, but normally it is empty (the system sharedlib search path isn’t there). If you have some important there, you can give him a colon-separated path list, just as we can see in $PATH : export LD_LIBRARY_PATH=/home/darkmoon/lib:/home/darkmoon/some_another/lib . or just so.
CMake project fails to find shared library
I am using CMake to build a cross platform project. For the moment I am trying to run it on Linux. I have recently added a project for running tests, but it will not run because it cannot find one of the shared libraries, specifically libtbbmalloc.so.2 :
/tests: error while loading shared libraries: libtbbmalloc.so.2: cannot open shared object file: No such file or directory`
linux-vdso.so.1 (0x00007fffeb572000) libtbbmalloc_proxy.so.2 => /home/username/dev/tbb/libtbbmalloc_proxy.so.2 (0x00007f50afe00000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f50afa70000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f50af6d0000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f50af4b0000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f50af0a0000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f50aee90000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f50aec70000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f50aea60000) /lib64/ld-linux-x86-64.so.2 (0x00007f50b0400000) libtbbmalloc.so.2 => not found
set(test_sourcefiles main_tests.cpp) add_executable(tests $) target_link_libraries(tests Catch2::Catch2 MyLib)
MyLib uses tbb, and I guess that is why my executable (tests) searches for it. When running ldd on MyLib it finds the library (libtbbmalloc.so.2):
(removed some output for readability) libtbbmalloc_proxy.so.2 => /home/username/dev/tbb/libtbbmalloc_proxy.so.2 (0x00007f9af8110000) libtbbmalloc.so.2 => /home/username/dev/tbb/libtbbmalloc.so.2 (0x00007f9ac4eb0000)
I have tried specifically adding libttbbmalloc.so.2 in my tests/CMakeLists.txt target_link_libraries($
larjr@DESKTOP:~/dev/project/build/tests$ chrpath -l tests tests: RUNPATH=/home/larsjr/dev/project/build/MyLib:/home/username/dev/tbb
Linux Program can’t find Shared Library at run-time
I’m guessing that this is the part that pulls in the lidid3 library? The file DOES exist, however, what they are looking for is actually a symbolic link to:
I’m wondering if it is an issue with it not being able to follow symbolic links? Perhaps I could manually change it to look for 0.0 if I knew where I was looking to change it. I’m happy to clarify any details. It looks like the includes are done in the following manner:
id3v2: convert.o list.o id3v2.o genre.o $ $ -pedantic -Wall -g -o $@ $^ -lz -lid3
I was able to use Simon’s advice to figure out that there were multiple spots where one might expect a library. I create a symbolic link where the program was linking to the ACTUAL file. Thank you Simon!
Your title asks about the header, but your question’s clearly about the shared library at runtime :-/. You might check if it works if you add the directory containing the symbolic link to your LD_LIBRARY_PATH environment variable.
I clearly don’t understand what I’m doing. I will try to read your statement and see if I can follow your advice.
Did you try running ldconfig as root? This program makes a registry of available libraries used for runtime library loading. The trick is that the library has to be in a place that ldconfig expects to see it, which depends on the distribution. The list of library directories is usually in /etc/ld.so.conf or somewhere similar.
3 Answers 3
Symlinks on libraries work fine, as long as the final target they trace to exists and is accessible.
You have built a dynamically-linked executable, that wishes to be linked against libid3-3.8.so.3 at execution time. This was likely linked during the build phase with something like -L/path/to/libid3/directory -lid3 .
You have a few options to make libid3 available, in generally decreasing order of preference (since you didn’t mention where the file was, I can only be general):
- Create a symlink to libid3* in a directory listed in /etc/ld.so.conf (or /lib or /usr/lib )
- Copy libid3* to a directory listed in /etc/ld.so.conf (or /lib or /usr/lib ) (defaults)
- Add the directory containing libid3* to /etc/ld.so.conf
- Set LD_LIBRARY_PATH=/directory/path/to/libid3* before running your id3v2 executable.
- Recompile id3v2 statically. (It will work, but don’t bother.)
After any of the first 3, rerun ldconfig so the linker cache is updated. (You can then run ldconfig -v to verify it’s resolvable.)
Note those aren’t steps, they’re options. You only need to do 1 of them.
Glad you updated the title. #include directives have nothing to do with linking.
Makefile — cannot find shared library
when i run ‘make’ it builds the project, with no errors. but when i run the project it complains that:
error while loading shared libraries: libsomeso.so: cannot open shared object file: No such file or directory
The path that i give in DIR goes to the folder where the shared object is held(relatively to where the makefile is placed), and if it was the wrong path why didn’t it complain during the make process. does someone know what am i missing? Thanks Matt
5 Answers 5
LDFLAGS += -L$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
LDFLAGS += -L$(DIR)/lib/linux -Wl,-R$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
That is, for each non-standard dynamic library location -L a corresponding -Wl,-R should be specified. $ORIGIN is needed to locate dynamic libraries relative to the executable, not sure if you need it here.
People often advise using LD_LIBRARY_PATH . This is a bad advice, in my opinion, because it makes deployment more complicated.
When you run your application, location of libsomeso.so should be in LD_LIBRARY_PATH environment variable. Try running program like this:
LD_LIBRARY_PATH="path_to_libsomeso_so:$LD_LIBRARY_PATH" myprogram
Here path_to_libsomeso_so is full path to a directory where libsomeso.so is located, and myprogram is your program executable. Note, that you should specify path to a directory containing libsomeso.so , not to libsomeso.so file itself.
The trouble is not during compilation time. Everything goes fine. There’s a problem at runtime.
Indeed, your program has been linked with a shared object library. Therefore, at runtime, it need to load this shared object file. During compilation, you instructs the compiler where this file was with the -L flag.
For the runtime, you have to set the LD_LIBRARY_PATH environment variable to point to the directory where your libsomeso.so file resides.
Alternatively, you can place this file in one of the standard directory where these shared object files are searched for: /usr/local/lib , /usr/lib , /lib , but this should be what you’ll do for the final distributed version of your library.
As told from Maxim Egorushkin, LD_LIBRARY_PATH is a bad choice. Meanwhile, using -L$(your lib path) -l$(your lib name) gcc/g++ argument to link shared library isn’t a good choice. Because, after build the exe, you should told exe where the shared library directory is. By default, executable file only search shared library at /usr/lib or /usr/local/lib . Although, you have told makefile where the shared library is when build the executable file. But when you execute this exe file, they are different. However, link static library don’t have such problem.
So, the best way to deal with your problem is change the way you link your custom shared file. Like this:
DYNAMIC_LIB_DIR = ../lib (your lib path ,this is a example) OBJLIBS = xxx.so (your lib name) gcc/g++ -o exe_name sourcefile/object_file $(DYNAMIC_LIB_DIR)/$(OBJLIBS)
Refresh that dynamic library cache!
After adding a custom, non-standard library to /usr/local/lib , first check that /usr/local/lib is listed under /etc/ld.so.conf.d/libc.conf .
Then, finish off with a dynamic link library cache refresh:
ld cannot find shared library
Note: I visited many topics with questions similar to this one, although solutions chosen as accepted were all things I’ve already tried, so please, consider this before marking as duplicate. Also, I’m new to Linux in general, so feel free to correct me if I say something fundamentally incorrect.
The problem:
- Compiled all .cpp files with -fPIC explicitly stated
- Created the library with g++ -shared -fPIC -Wl,-soname,libcustom_program_options.so.1 -o libcustom_program_options.so.1.0.1 *.o
- Ran ldconfig to update the loader cache like this: sudo ldconfig -n /usr/local/lib
And when I try to link the library against my test program:
g++ main.cpp -o main -L /usr/local/lib -l libcustom_program_options
/usr/bin/ld: cannot find -llibcustom_program_options
collect2: error: ld returned 1 exit status
Note: I wasn’t sure if ld was looking for the library’s full-name or soname or maybe the «name between lib- and .so.», so I tried each one of those. Didn’t help either.
Did you try -lcustom_program_options ? the l is usually expanded to lib (so for example -lm links libm.so and so on)
Yes, I did. By saying «name between lib- and .so.
1 Answer 1
Ok, I finally managed to solve it.
Once I checked what file the linker is actually expecting to find, I knew what to do next.
ld -L/usr/local/lib -lcustom_program_options --verbose
Where /usr/local/lib is the directory I put the library in, and custom_program_options is the name of the library stripped of the lib- prefix and all prefixes (i.e. extension and version).
As it printed a list of all considered directories along with the exact expected file name, I knew that it was looking for libcustom_program_options.so, whilst calling ldconfig (mentioned in the OP) set a link only between libcustom_program_options.so.1 and libcustom_program_options.so.1.0.1 (note the version number).
The file ld was trying to find indeed never existed.
The solution was to create the link manually:
sudo ln -s /usr/local/lib/libcustom_program_options.so.1 /usr/local/lib/libcustom_program_options.so
So this pretty much solved it. The culprit was me not knowing what was the exact filename sought by the linker.