1. Overview

In this tutorial, we’ll go through various causes and fixes for the cannot open shared object file: No such file or directory” error in Linux.

2. What Are Shared Libraries?

Shared libraries in Linux provide various re-usable functions for programs.

Say we want to write a program that takes compressed files as input. To do this, we can use existing libraries such as zlib instead of implementing the decompression functions ourselves.

Programs load shared libraries on launch.

Further, we can list all the shared libraries used by a program with the ldd command:

$ ldd /usr/bin/clang
/usr/bin/clang:
	linux-vdso.so.1 (0x00007ffd34a90000)
	libclang-cpp.so.13 => /usr/bin/../lib/libclang-cpp.so.13 (0x00007f24c5a94000)
	libLLVM-13.so => /usr/bin/../lib/libLLVM-13.so (0x00007f24c1548000)
	libstdc++.so.6 => /usr/bin/../lib/libstdc++.so.6 (0x00007f24c12d6000)
	libm.so.6 => /usr/bin/../lib/libm.so.6 (0x00007f24c11f8000)
	libgcc_s.so.1 => /usr/bin/../lib/libgcc_s.so.1 (0x00007f24c11dd000)
	libc.so.6 => /usr/bin/../lib/libc.so.6 (0x00007f24c0fc4000)
	/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007f24c95d4000)
	libz.so.1 => /usr/bin/../lib/../lib/libz.so.1 (0x00007f24c0fad000)

Here, we can see that the clang compiler requires various libraries such as LLVM for its functioning.

As we can see, shared libraries end with the .so extension.

Sometimes, the shared library might not exist or might be located in a non-standard path. As a result, we get the cannot open shared object file: No such file or directory” at program launch.

3. Missing Packages

Sometimes, we might just be missing the package that provides the required shared library.

For example, if a program complains about a missing libzstd.so, we can try searching for it in our system’s package manager.

On apt-based systems, we can use the apt search command:

$ apt search zstd
Sorting... Done
Full Text Search... Done
zstd/stable 1.5.0 aarch64
  Zstandard compression.

Now, we can install the missing package with apt install. However, we must note that this method is not very reliable and requires some guesswork for finding the package name.

In the above example, the missing library’s name was libzstd.so, but there is no package called libzstd. As a result, we had to guess and search for just zstd instead.

4. The LD_LIBRARY_PATH Variable

We can specify the directories to be searched for shared libraries in the LD_LIBRARY_PATH environment variable.

LD_LIBRARY_PATH is a colon-separated list of directories, just like the PATH variable.

The default search path is usually limited to /usr/lib and /usr/local/lib.

Say we have a program that links to libfoo.so, located at /home/baeldung/libs/libfoo.so, which lies outside the default search path. Then, we can use this variable to append to the search path and solve the issue.

First, let’s confirm the exact libraries that the program links to using the ldd command:

$ ./program
./program: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
$ ldd ./program
./program:
	linux-vdso.so.1 (0x00007ffce871b000)
	libfoo.so => not found
	libc.so.6 => /usr/lib/libc.so.6 (0x00007fdceadaf000)
	/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007fdceafd3000)

Now, let’s add the directory to LD_LIBRARY_PATH and make our program work:

$ export LD_LIBRARY_PATH=/home/baeldung/libs
$ ldd ./program
./program:
	linux-vdso.so.1 (0x00007ffe28dfd000)
	libfoo.so => /home/baeldung/libs/libfoo.so (0x00007f8f0f7ba000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007f8f0f59d000)
	/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007f8f0f7c6000)

Additionally, if we don’t know where the library is, we can locate it using the find command in common paths such as /home or /usr:

$ find /home -type f -name libfoo.so
/home/baeldung/libs/libfoo.so

5. Configuring Library Path Permanently

We can use the /etc/ld.so.conf file to permanently set the library search path. In this file, we specify a newline-separated list of directories.

Let’s fix the libfoo.so error again:

$ ./program
./program: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
$ echo "/home/baeldung/libs" | sudo tee /etc/ld.so.conf
/home/baeldung/libs
$ sudo ldconfig
$ ldd ./program
./program:
	linux-vdso.so.1 (0x00007ffefc3db000)
	libfoo.so => /home/baeldung/libs/libfoo.so (0x00007f021e88d000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007f021e674000)
	/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007f021e89e000)

We must run the ldconfig command once to make the system aware of the new paths.

6. The ldconfig Command

We might have recently installed new shared libraries or modified the shared library search paths. As a result, we need to run the ldconfig command.

It updates the linker’s cache to make it aware of new shared libraries.

The linker, known as ld.so loads shared libraries for programs.

We can invoke ldconfig with the -p flag to inspect the current cache:

$ ldconfig -p
347 libs found in cache `/etc/ld.so.cache'
	libzstd.so.1 (libc6,x86-64) => /usr/lib/libzstd.so.1
	libzstd.so (libc6,x86-64) => /usr/lib/libzstd.so
	libz.so.1 (libc6,x86-64) => /usr/lib/libz.so.1
	libz.so (libc6,x86-64) => /usr/lib/libz.so
	libx265.so.199 (libc6,x86-64) => /usr/lib/libx265.so.199
	libx265.so (libc6,x86-64) => /usr/lib/libx265.so
	libx264.so.157 (libc6,x86-64) => /usr/lib/libx264.so.157
	libx264.so (libc6,x86-64) => /usr/lib/libx264.so
...

From this output, we can identify the exact location of various shared libraries.

7. Setting the Library Path at Compile Time

If we have access to the program’s source code, we can compile it with special flags during the linking process so that the shared libraries can be located.

We can pass a library path to the dynamic linker at runtime with ld‘s -rpath flag.

Let’s compile a basic program and link it to our library:

$ pwd
/home/baeldung/libs
$ ls
libfoo.so
$ echo "int main() {}" > program.c # Dummy program
$ cc program.c libfoo.so # Link to our library
$ ./a.out 
./a.out: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
$ ldd ./a.out 
./a.out:
	linux-vdso.so.1 (0x00007ffcbc1f8000)
	libfoo.so => not found
	libc.so.6 => /usr/lib/libc.so.6 (0x00007feb0ee04000)
	/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007feb0f029000)

We can see that the program fails to load our shared library.

Now, let’s try compiling it with the -rpath flag, adding /home/baeldung/libs to the library search path:

$ gcc program.c libfoo.so -Wl,-rpath=/home/baeldung/libs
$ ldd ./a.out 
./a.out:
	linux-vdso.so.1 (0x00007ffd0fbad000)
	libfoo.so => /home/baeldung/libs/libfoo.so (0x00007fba09d99000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007fba09b7b000)
	/lib/ld-linux-x86-64.so.2 => /usr/lib/ld-linux-x86-64.so.2 (0x00007fba09da5000)

Here, we’ve used gcc‘s -Wl flag to pass arguments to ld.

8. Conclusion

In this article, we covered the various reasons for missing shared libraries and their solutions. Additionally, we covered the working of the dynamic linker that loads shared libraries for programs.

Comments are closed on this article!