Resolving “Shared Library Not Found” Error When .so File Exists in Same Directory as Executable


3 views

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:

  1. The LD_LIBRARY_PATH environment variable
  2. The library path cache (/etc/ld.so.cache)
  3. 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:

  1. Add your library directory to /etc/ld.so.conf
  2. Run sudo ldconfig to update the cache
  3. Consider using standard library paths (/usr/local/lib) for production deployments