How shared library locations are found at runtime

You have successfully compiled an executable that is linked with one or more external shared libraries. You can view the shared libraries that the executable is dependent on by using the ldd tool. When you actually run the executable, the dynamic linker-loader ld-linux looks for each dependent shared library in the following locations, in order:

  • Using RPATH, if it exists, that is hard-coded in the executable. This is a colon-separated list of directories from where the shared libraries were linked into the executable by the linker during the linking stage of compilation. If this exists, you can view it using this command: readelf -d ./your_binary | grep RPATH
  • Using LD_LIBRARY_PATH, if it is set. This is a colon-separated list of directories set as an environment variable by the user.
  • Using RUNPATH, it is exists, that is hard-coded in the executable. This is a colon-separated list of directories, just like RPATH. If this exists, you can view it using this command: readelf -d ./your_binary | grep RUNPATH
  • Checks the /etc/ld.so.cache. This cache is populated by running the ldconfig program. This program is usually run when libraries are installed. You can view the shared libraries in the cache using this command: ldconfig -p
  • Check in /lib
  • Check in /usr/lib

See it in action

You can actually witness the loader searching directories to find the location of each shared library. To see this in action, try this command:

$ LD_DEBUG=libs ldd ./some_executable

In the output of this command, you will see that:

  • Each shared library listed in the executable is picked up in order.
  • For each shared library, the locations listed above (RPATH, LD_LIBRARY_PATH, RUNPATH, cache, lib and user lib) are tried in order.
  • For each directory listed in the above colon-separated list, the shared library filename is appended and tried to see if the file path exists.
  • The first instance where such a file path exists, that is noted as the location of the shared library.

References:

Advertisements

How to build and use GLFW

GLFW is a library for OpenGL created by Camilla Berglund. It is a modern replacement to GLUT, to draw windows and handle input.

GLFW 2.x

Ubuntu ships with an ancient version of GLFW that can be installed easily:

$ sudo apt install libglfw-dev

However, it is highly recommended to use GLFW 3.x. It has a different API and your source code and build options will need to be changed to use it.

To remove this ancient GLFW:

$ sudo apt remove libglfw-dev glfw2

GLFW 3.x

I like to install GLFW from Github. You could also get one of its stable releases, the installation steps would be the same for either.

  • Get the source:
$ git clone https://github.com/glfw/glfw.git
  • Build the library. Note that we request CMake to create shared library files. Why this is not the default on Linux puzzles me!
$ cd glfw
$ mkdir build
$ cd build
$ cmake -D BUILD_SHARED_LIBS=ON ..
  • Install the library:
$ sudo make install

Note that I highly recommend using checkinstall as described here instead of doing this.

  • Update the dynamic linker cache, so that the libglfw.so shared library file can be loaded at runtime:
$ sudo ldconfig

If you do not do this, you get an error similar to that described here.

  • To use GLFW 3.x calls in your code, include the header file:
#include <GLFW/glfw3.h>
  • To link and build your code use the library directive: -lglfw to your build options or CMake.

Tried with: GLFW 20150825 and Ubuntu 14.04

How to fix shared object file error

Problem

One of the most common errors a programmer faces is when an executable is run and it fails to find a required shared library. The error is usually of this form:

hello-world-program: error while loading shared libraries: libFoobar.so.1: cannot open shared object file: No such file or directory

However, you might know that the shared library file libFoobar.so.1 actually exists, say in a directory named /opt/foobar/lib. But, for some reason the ld-linux dynamic loader-linker is not looking in this directory.

Solution

It is important to know which are the locations that the loader searches for a given shared library file. This is described in this post.

After reading the above post, you can see that the error is caused because the shared library file is not found in the locations listed in that post. Of all those locations, the two places which are easy to modify are at the user-level (LD_LIBRARY_PATH) and at the system-level (shared library cache).

Add to LD_LIBRARY_PATH

Set this at shell for temporary use or add to the shell initialization file for permanent effect:

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/foobar/lib

If your shared library is located in the same directory as the executable, then you can add . to LD_LIBRARY_PATH.

Update system cache

  • Open the /etc/ld.so.conf as sudo and add a new line with the library directory. In this case, we add /opt/foobar/lib.

  • Rerun ldconfig to rebuild the cache:

$ sudo ldconfig
  • Check if the shared library cache now includes the shared libraries from the new directory:
$ ldconfig -p

Your program should now execute without any errors 🙂

Tried with: Ubuntu 14.04