- Linux error while loading shared libraries: cannot open shared object file: No such file or directory
- 19 Answers 19
- ldconfig
- Dev package or wrong version
- Library location
- Guide to Object File Linking
- What is a linker?
- What is an object file?
- Relocatable object file
- Extra: Relocatable Object File
- Executable Object Files
- Shared Object Files
- How to create a shared object file
- What does ELF stand for?
- What is an ELF file?
- Resources
- How do I load a shared object in C++?
- 4 Answers 4
Linux error while loading shared libraries: cannot open shared object file: No such file or directory
Program is part of the Xenomai test suite, cross-compiled from Linux PC into Linux+Xenomai ARM toolchain.
# echo $LD_LIBRARY_PATH /lib # ls /lib ld-2.3.3.so libdl-2.3.3.so libpthread-0.10.so ld-linux.so.2 libdl.so.2 libpthread.so.0 libc-2.3.3.so libgcc_s.so libpthread_rt.so libc.so.6 libgcc_s.so.1 libstdc++.so.6 libcrypt-2.3.3.so libm-2.3.3.so libstdc++.so.6.0.9 libcrypt.so.1 libm.so.6 # ./clocktest ./clocktest: error while loading shared libraries: libpthread_rt.so.1: cannot open shared object file: No such file or directory
This might happen if you have recently installed a shared library and didn’t run ldconfig(8) afterwards. Do ‘ldconfig’, there’s no harm in it.
+1 to @AbiusX comment — running sudo ldconfig (assuming that libraries are in fact where they should be [/usr/bin/lib/, /usr/bin/include/, /usr/local/lib/ and /usr/local/include/ AFAIK], please correct me if I’m wrong) can resolve that problem. Cheers!
Note that this error can also arise if the permissions on your lib file got changed somehow. Changing the permissions back to 644 solved it for me.
@AbiusX I ran sudo ldconfig after compiling my program and it worked. Thanks! (The libraries were in /usr/local/lib.)
19 Answers 19
Your library is a dynamic library. You need to tell the operating system where it can locate it at runtime.
To do so, we will need to do those easy steps:
- Find where the library is placed if you don’t know it.
sudo find / -name the_name_of_the_file.so
LD_LIBRARY_PATH=/usr/local/lib
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/my_library/ export LD_LIBRARY_PATH ./my_app
The above mentioned answer was very clear, Thanks you first of all. I tried doing this in my Eclipse CDT Project Path (Lubuntu). /Debug$ echo $LD_LIBRARY_PATH /home/akhil/HDE/x86.linux/lib:/home/akhil/HDE/x86.linux/lib.. «/home/akhil/HDE/x86.linux/lib» this is where my libraries are actually available even, but still I get the same error. Any suggestions!
Try a «ldconfig» command after exporting your library. You might need to execute this command as «sudo».
I believe LD_LIBRARY_PATH should point to the directory containing path.so.something , not to path.so.something itself.
This is the right solution for the systems where sudo ldconfig cannot be executed, e.g. supercomputers.
The export LD_LIBRARY_PATH command is essential so that other programs can read the environment variable. Without it only the shell can see the variable.
Here are a few solutions you can try:
ldconfig
As AbiusX pointed out: If you have just now installed the library, you may simply need to run ldconfig.
ldconfig creates the necessary links and cache to the most recent shared libraries found in the directories specified on the command line, in the file /etc/ld.so.conf, and in the trusted directories (/lib and /usr/lib).
Usually your package manager will take care of this when you install a new library, but not always, and it won’t hurt to run ldconfig even if that is not your issue.
Dev package or wrong version
If that doesn’t work, I would also check out Paul’s suggestion and look for a «-dev» version of the library. Many libraries are split into dev and non-dev packages. You can use this command to look for it:
This can also help if you simply have the wrong version of the library installed. Some libraries are published in different versions simultaneously, for example, Python.
Library location
If you are sure that the right package is installed, and ldconfig didn’t find it, it may just be in a nonstandard directory. By default, ldconfig looks in /lib , /usr/lib , and directories listed in /etc/ld.so.conf and $LD_LIBRARY_PATH . If your library is somewhere else, you can either add the directory on its own line in /etc/ld.so.conf , append the library’s path to $LD_LIBRARY_PATH , or move the library into /usr/lib . Then run ldconfig .
To find out where the library is, try this:
sudo find / -iname *libraryname*.so*
(Replace libraryname with the name of your library)
If you go the $LD_LIBRARY_PATH route, you’ll want to put that into your ~/.bashrc file so it will run every time you log in:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/library
By default, /lib and /usr/lib but not /usr/local/lib? That has thrown me off several times over my career and wasted hours.
Adding .conf files of my own with the non-standard lib paths I need to /etc/ld.so.conf.d (pointed to by /etc/ld.so.conf ) did the trick.
+1 for needing to run ldconfig. I wasn’t using a package manager. I had to compile from source, so this was necessary.
Just like @CivFan, I added my own .conf in /etc/ld.so.conf.d . After which I (obviously) had to run ldconfig and it worked. I can feel you @DarenW. Its a pain in the butt
Update
While what I write below is true as a general answer about shared libraries, I think the most frequent cause of these sorts of message is because you’ve installed a package, but not installed the -dev version of that package.
Well, it’s not lying — there is no libpthread_rt.so.1 in that listing. You probably need to re-configure and re-build it so that it depends on the library you have, or install whatever provides libpthread_rt.so.1 .
Generally, the numbers after the .so are version numbers, and you’ll often find that they are symlinks to each other, so if you have version 1.1 of libfoo.so, you’ll have a real file libfoo.so.1.0, and symlinks foo.so and foo.so.1 pointing to the libfoo.so.1.0. And if you install version 1.1 without removing the other one, you’ll have a libfoo.so.1.1, and libfoo.so.1 and libfoo.so will now point to the new one, but any code that requires that exact version can use the libfoo.so.1.0 file. Code that just relies on the version 1 API, but doesn’t care if it’s 1.0 or 1.1 will specify libfoo.so.1. As orip pointed out in the comments, this is explained well at here.
In your case, you might get away with symlinking libpthread_rt.so.1 to libpthread_rt.so . No guarantees that it won’t break your code and eat your TV dinners, though.
Guide to Object File Linking
A compiler driver performs the following:
- preprocesses source file (e.g., replace #include with code)
- converts high level source file to assembly language
- runs the assembler to convert the assembly language into a relocatable object file with machine code
- performs the above steps for the other source files
- runs a linker program like ld to combine all the object files into an executable object file
What is a linker?
A program that combines one or more object files generated by the compiler into a single file that can be copied into memory and executed.
What is an object file?
Object files contain binary code. There are three forms of object files:
Relocatable object file
Assemblers produce relocatable object files. They are “relocatable” because the functions and variables are not bound to any specific address. Instead, the addresses are still symbols.
This file contains binary code and data that can be combined with other relocatable object files at compile time to create an executable object file.
An example of a relocatable object file might be a collection of math functions.
/* math.c * A simple math library */ int add(int a, int b) return a + b; >
unix > gcc -c math.c # Create relocatable obj file (math.o) unix > readelf -h math.o | grep Type # Read math.o with readelf Type: REL (Relocatable file) # and verify its type
This relocatable object file can now be compiled with any other program to create an executable object file.
/* math.h */ #ifndef MATH_H #define MATH_H int add(int a, int b); #endif /* math_test.c */ #include #include "math.h" int main(void) int result = add(1, 2); printf("result: %d\n", result); return 0; >
unix > gcc math_test.c -o math_test /tmp/cclRibQq.o: In function `main': math_test.c:(.text+0x19): undefined reference to `add' collect2: ld returned 1 exit status
What just happened? Why couldn’t I produce a math_test program? My math_test program references the add method, but the implementation for the add method is in the math.o relocatable object file. The gcc compiler system doesn’t know that, so it can’t magically link the math.o file with my program. Thus, I must specify that I’m linking in math.o.
unix > gcc math_test.c math.o -o math_test unix > ./math_test result: 3
Extra: Relocatable Object File
To more deeply understand the meaning of “relocatable”, look at the difference between the symbol tables of a relocatable object file and an executable object file.
unix > gcc -c main.c unix > readelf --symbols main.o Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS main.c 2: 00000000 0 OBJECT GLOBAL DEFAULT 3 buf 3: 00000000 0 OBJECT GLOBAL DEFAULT 1 main unix > gcc main.c -o main unix > readelf --symbols main Num: Value Size Type Bind Vis Ndx Name 53: 08048460 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini 54: 08048462 0 FUNC GLOBAL HIDDEN 13 __i686.get_pc_thunk.bx 55: 0804a018 4 OBJECT GLOBAL DEFAULT 13 bufp0
Above are excerpts of the object files. The relocatable object file has symbols associated with the 00000000 address. The executable object file has symbols associated with real addresses. After the compiler and assembler generate the relocatable object file, the data start at address 0. The linker then relocates these sections by associating each with a location with in memory.
Executable Object Files
Having seen in detail what a relocatable object file is, it should be no surprise that an executable object file is simply a relocatable object file with the addresses assigned so that it can be placed into memory for execution. There are a few other details, but at a high level, this is the most important.
At the command line, if the program is invoked, a program called the loader copies the code and data from the executable into main memory. The loader then runs the program by jumping to the instruction at the entry point, which is always at the address of the start symbol.
The code at _start usually runs some initialization code. Then it runs the main routine, which is defined in every C program. Finally it runs _exit.
Shared Object Files
Relocatable object files are linked together during compile time. As stated before, once the symbols in the relocatable object files are assigned addresses, those cannot be changed unless the compilation process is done again. Another disadvantage is the entire object file is linked into the final executable object file.
A modern innovation is the development of shared object files, which are linked into programs during runtime. This is also known as dynamic linking.
Each file system only has one of each shared object file. Each program that uses the shared object file is using the exact same machine code as well. They are suffixed by .so.
How to create a shared object file
unix > gcc -shared -fPIC -o libtest.so test.c
What does ELF stand for?
executable and linkable format
What is an ELF file?
An ELF file is a file containing binary data.
Resources
Software engineering thoughts and advice
How do I load a shared object in C++?
I have a shared object (a so — the Linux equivalent of a Windows dll) that I’d like to import and use with my test code. I’m sure it’s not this simple 😉 but this is the sort of thing I’d like to do..
#include "headerforClassFromBlah.h" int main()
I assume that this is a really basic question but I can’t find anything that jumps out at me searching the web.
Maybe im confused but you don’t look like you have enough info there. What does blah.so contain, for example? You sure you aren’t just talking about using a reference?
Err. so files are not code files, right? Maybe you want to retrieve an object from a .so (shared library) file?
4 Answers 4
There are two ways of loading shared objects in C++
For either of these methods you would always need the header file for the object you want to use. The header will contain the definitions of the classes or objects you want to use in your code.
#include "blah.h" int main() < ClassFromBlah a; a.DoSomething(); >gcc yourfile.cpp -lblah
#include #include #include int main(int argc, char **argv) < void *handle; double (*cosine)(double); char *error; handle = dlopen ("libm.so", RTLD_LAZY); if (!handle) < fprintf (stderr, "%s\n", dlerror()); exit(1); >dlerror(); /* Clear any existing error */ cosine = dlsym(handle, "cos"); if ((error = dlerror()) != NULL) < fprintf (stderr, "%s\n", error); exit(1); >printf ("%f\n", (*cosine)(2.0)); dlclose(handle); return 0; >
*Stolen from dlopen Linux man page The process under windows or any other platform is the same, just replace dlopen with the platforms version of dynamic symbol searching.
For the dynamic method to work, all symbols you want to import/export must have extern’d C linkage.
There are some words Here about when to use static and when to use dynamic linking.