When working with dynamic linking in Linux, it's common to assume that placing a shared library (.so
file) in the same directory as your executable would automatically make it discoverable. However, this assumption often leads to the frustrating error:
error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
The Linux dynamic linker (ld.so) doesn't automatically search the executable's directory. Instead, it follows a specific search path defined by:
- The
LD_LIBRARY_PATH
environment variable - The library path cache (
/etc/ld.so.cache
) - Default system library paths (
/lib
,/usr/lib
, etc.)
Here are several ways to resolve this issue:
Solution 1: Using rpath
Add the library path to the executable during linking:
gcc -o binary source.c -L. -ltest -Wl,-rpath='$ORIGIN'
The special $ORIGIN
token represents the executable's directory.
Solution 2: Temporary LD_LIBRARY_PATH
Run your program with:
LD_LIBRARY_PATH=. ./binary
Solution 3: Permanent System Configuration
Add your library path to the system configuration:
echo '/path/to/your/libs' | sudo tee /etc/ld.so.conf.d/myapp.conf
sudo ldconfig
When examining your binary with readelf -d binary
, you might see these tags:
- DT_RPATH: Obsolete but still supported, set via
-rpath
- DT_RUNPATH: Modern alternative, set via
--enable-new-dtags
For maximum compatibility:
gcc -o binary source.c -L. -ltest -Wl,-rpath='$ORIGIN',--enable-new-dtags
Verify your library paths with:
ldd ./binary
When working with dynamic libraries in Linux environments, a common frustration occurs when the runtime linker fails to locate a shared library (.so
file) even when it exists in the same directory as the executable. Let's explore why this happens and how to properly configure your environment.
The Linux dynamic linker (ld.so
) doesn't automatically search the executable's directory for shared libraries. Instead, it looks in these locations by default:
1. Directories listed in the executable's RPATH/RUNPATH
2. LD_LIBRARY_PATH environment variable
3. /etc/ld.so.cache (which typically includes /lib and /usr/lib)
4. /lib and /usr/lib (as fallbacks)
Here are three effective approaches to resolve this issue:
Method 1: Using LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)
./binary
Method 2: Setting RPATH During Compilation
For a more permanent solution, you can embed the library path in the executable:
gcc -o binary source.c -L. -ltest -Wl,-rpath='$ORIGIN'
The $ORIGIN
special variable refers to the executable's directory.
Method 3: Creating a Wrapper Script
#!/bin/bash
SCRIPT_DIR=$(dirname $(readlink -f "$0"))
LD_LIBRARY_PATH=$SCRIPT_DIR:$LD_LIBRARY_PATH exec "$SCRIPT_DIR/binary" "$@"
Use the ldd
tool to examine library dependencies and paths:
ldd ./binary
This will show which libraries are found and which are missing.
For system-wide solutions, you can:
- Add your library directory to /etc/ld.so.conf
- Run
sudo ldconfig
to update the cache - Consider using standard library paths (/usr/local/lib) for production deployments