The solution by Max Ghenis and ManuelAtWork helped me with a related issue with a different shared library. I wanted to document my steps here in case it helps somebody else.
TL;DR
Even if LD_LIBRARY_PATH
contains /usr/local/lib
, and your shared object library ( the .so
file ) is located there, you still might get an error like
error while loading shared libraries: <INSERT LIBRARY NAME>.so.0: cannot open shared object file: No such file or directory
If your linker cache /etc/ld.so.cache
has not been rebuilt since the library was installed.
You can fix this by running ldconfig
( or sudo ldconfig
, depending on the /etc
directory permissions, which are likely only writeable by the root user ).
When successful, ldconfig
prints no output. For more detailed output when running ldconfig
, use the -v
( or --verbose
) flag.
If you have ever run into this error, and then it magically fixed itself while you were troubleshooting, it's probably because you followed someone's advice and did something like
ldconfig -v | grep <INSERT LIBRARY NAME>
to make sure the .so
file was in a directory listed in LD_LIBRARY_PATH, like /usr/local/lib
. It's a reasonable troubleshooting step to perform if you already confirmed that directory is included in /etc/ld.so.conf
or /etc/ld.so.conf.d/*.conf
, but ldconfig -v
still runs ldconfig
in verbose mode, which rebuilds /etc/ld.so.cache
, and probably fixed your issue.
If your error mysteriously fixed itself after some time without you having to run ldconfig
, then something else on your system must have run it since then - e.g. a startup script, a scheduled task, or installation scripts for other software.
Details
I recently installed libhttpserver
, following the instructions on its GitHub repo, which follow the standard steps with the make
command. I was able to compile an external program against the library, but when I ran my program I received the same error related to dynamic linkage.
$ g++ -o server server.c `pkg-config --cflags --libs libhttpserver`
./server
error while loading shared libraries: libhttpserver.so.0: cannot open shared object file: No such file or directory
I confirmed pkg-config
knew linker flags and library names, meaning the .pc
file(s) for libhttpserver
had been installed correctly.
$ pkg-config --cflags --libs libhttpserver
-I/usr/local/include -I/usr/local/include/httpserver -I/usr/include/p11-kit-1 -L/usr/local/lib -lhttpserver -lmicrohttpd
I noted the -L/usr/local/lib
flag, and confirmed the shared object files were located there.
$ find /usr/local/lib -name '*httpserver*'
/usr/local/lib/libhttpserver.so.0
/usr/local/lib/libhttpserver.la
/usr/local/lib/libhttpserver.so.0.19.0
/usr/local/lib/pkgconfig/libhttpserver.pc
/usr/local/lib/libhttpserver.a
/usr/local/lib/libhttpserver.so
Following a suggestion from this thread, I searched for the library name in the output of ldconfig -v
$ ldconfig -v |grep libhttpserver
/sbin/ldconfig.real: Path `/usr/lib/x86_64-linux-gnu' given more than once
(from /etc/ld.so.conf.d/x86_64-linux-gnu.conf:4 and /etc/ld.so.conf.d/x86_64-linux-gnu.conf:3)
/sbin/ldconfig.real: Path `/usr/lib32' given more than once
(from /etc/ld.so.conf.d/zz_i386-biarch-compat.conf:3 and /etc/ld.so.conf.d/zz_i386-biarch-compat.conf:2)
/sbin/ldconfig.real: Path `/usr/libx32' given more than once
(from /etc/ld.so.conf.d/zz_x32-biarch-compat.conf:3 and /etc/ld.so.conf.d/zz_x32-biarch-compat.conf:2)
/sbin/ldconfig.real: Path `/lib/x86_64-linux-gnu' given more than once
(from <builtin>:0 and /etc/ld.so.conf.d/x86_64-linux-gnu.conf:3)
/sbin/ldconfig.real: Path `/usr/lib/x86_64-linux-gnu' given more than once
(from <builtin>:0 and /etc/ld.so.conf.d/x86_64-linux-gnu.conf:3)
/sbin/ldconfig.real: Path `/usr/lib' given more than once
(from <builtin>:0 and <builtin>:0)
libhttpserver.so.0 -> libhttpserver.so.0.19.0
/sbin/ldconfig.real: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 is the dynamic linker, ignoring
/sbin/ldconfig.real: /lib32/ld-linux.so.2 is the dynamic linker, ignoring
/sbin/ldconfig.real: Can't create temporary cache file /etc/ld.so.cache~: Permission denied
I noticed the error message at the end of the output
/sbin/ldconfig.real: Can't create temporary cache file /etc/ld.so.cache~: Permission denied
I decided to read the man page for ldconfig
to learn more about what ldconfig -v
was doing.
ldconfig creates the necessary links and cache to the most recent shared libraries found in the di‐rectories specified on the command line, in the file /etc/ld.so.conf, and in the trusted directories, /lib and /usr/lib
-v, --verbose
Verbose mode. Print current version number, the name of each directory as it is scanned, and
any links that are created. Overrides quiet mode.
Since ldconfig -v
flag was doing the same thing as ldconfig
, but just with more detailed output, I decided to run ldconfig
without it.
$ ldconfig
/sbin/ldconfig.real: Can't create temporary cache file /etc/ld.so.cache~: Permission denied
This time the error message from before was the only output. Before resorting to using sudo
, I wanted to learn more about what was happening. Since ldconfig
was trying to create a file called /etc/ld.so.cache~
, I decided to look for that file or files with similar names.
$ find /etc -name 'ld.so*'
/etc/ld.so.cache
find: ‘/etc/ssl/private’: Permission denied
find: ‘/etc/softhsm’: Permission denied
/etc/ld.so.conf.d
find: ‘/etc/polkit-1/localauthority’: Permission denied
find: ‘/etc/cups/ssl’: Permission denied
/etc/ld.so.conf
I figured /etc/ld.so.cache
must be the cache the ldconfig
man page was talking about. I decided to look for my library name there.
$ grep libhttpserver /etc/ld.so.cache
But grep
returned no matches. Instead I looked for /usr/local/lib
.
$ grep /usr/local/lib /etc/ld.so.cache
grep: /etc/ld.so.cache: binary file matches
That found a match. Reading the man pages for ldconfig
, I learned the -p
flag prints the cache, which is a binary file, in a human readable format, so I searched for /usr/local/lib
in the output of ldconfig -p
.
ldconfig -p | grep /usr/local/lib
I found matches for other libraries in /usr/local/lib
(e.g. libwayland, but not libhttpserver
.
libwayland-server.so.0 (libc6,x86-64) => /usr/local/lib/x86_64-linux-gnu/libwayland-server.so.0
libwayland-server.so (libc6,x86-64) => /usr/local/lib/x86_64-linux-gnu/libwayland-server.so
libwayland-egl.so.1 (libc6,x86-64) => /usr/local/lib/x86_64-linux-gnu/libwayland-egl.so.1
libwayland-egl.so (libc6,x86-64) => /usr/local/lib/x86_64-linux-gnu/libwayland-egl.so
libwayland-cursor.so.0 (libc6,x86-64) => /usr/local/lib/x86_64-linux-gnu/libwayland-cursor.so.0
libwayland-cursor.so (libc6,x86-64) => /usr/local/lib/x86_64-linux-gnu/libwayland-cursor.so
libwayland-client.so.0 (libc6,x86-64) => /usr/local/lib/x86_64-linux-gnu/libwayland-client.so.0
libwayland-client.so (libc6,x86-64) => /usr/local/lib/x86_64-linux-gnu/libwayland-client.so
...
Clearly the linker ld.so
had at one point been able to find libraries located in /usr/local/lib
, because they were in the linker's cache. I confirmed this was still the case by checking /etc/ld.so.conf
and /etc/ld.so.conf.d
.
$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
$ grep -x /usr/local/lib /etc/ld.so.conf.d/*.conf
/etc/ld.so.conf.d/libc.conf:/usr/local/lib
I was curious what was normally responsible for running ldconfig
on my system, but I couldn't find a systemd service, crontab, or init.d script responsible for running it. I had built libraries from source before that were installed to /usr/local/lib
, but I never had this issue.
I finally did find a reference to ldconfig
in a build script in the source code for one such library I had installed a while ago. I concluded it was up to the author of the source code whether or not to run ldconfig
after installation, and that whether or not the system runs ldconfig
automatically on startup, etc., depends on what Linux distribution you're using.
Having convinced myself I wasn't doing any harm by rebuilding the linker cache, I finally resorted to running ldconfig
as root.
sudo ldconfig
This time, there was no error message about failing to create a temporary cache file. Before attempting to run my code again, I confirmed the linker cache now contained a reference to libhttpserver
.
$ ldconfig -p|grep libhttpserver
libhttpserver.so.0 (libc6,x86-64) => /usr/local/lib/libhttpserver.so.0
libhttpserver.so (libc6,x86-64) => /usr/local/lib/libhttpserver.so
Finally, I tried to run program again and was successful.
$ ./server
Note that I didn't need to recompile my program after running sudo ldconfig
, since it already contained references to the correct shared library. The issue was just that the linker cache /etc/ld.so.cache
needed to be updated by running sudo ldconfig
after installing libhttpserver
.
When you build libraries from source, you may run into this issue, depending on whether or not the source maintainers choose to include that step in their installation scripts.