From LQWiki
Jump to: navigation, search


If you are a programmer, you will want to re-use code written by others and design your program to be modular. You build up libraries containing re-usable code. Here is a library that contains functions for the KDE graphical user interface:

$ file /usr/lib64/
/usr/lib64/ ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped

There are two types of linking to libraries:

  • static linking takes the code from the library and combines it with the main program's code into an executable
  • dynamic linking forms an executable that loads the library code when it is executed.

Dynamic linking has the advantages:

  • if you link against a software with a bug in the library, this bug can be fixed without the need to touch your executable.
  • if more than one executable uses the same shared library, the overall memory consumption is lower
  • the executable needs less disc space

Statically linked executables have the advantages:

  • they do not depend on other libraries in the system that may not yet be installed. (important if you set up Linux from scratch).
  • you can use them in another distribution that might have different libraries installed
  • you can be sure how they will behave - less testing effort

"dynamically linked libraries" are also called "shared libraries" or "shared objects" on Linux. Their extension typically is .so (usually plus some version numbers). On MS Windows the extension is .dll, on Mac OS X, .dylib.

Shared Libraries

Find out dependencies

To find out which shared objects are required by an application, use ldd:

bash$ ldd /usr/X11R6/bin/glxgears => /usr/X11R6/lib/ (0x4001a000) => /usr/X11R6/lib/ (0x40080000) => /usr/X11R6/lib/ (0x4008e000) => /lib/ (0x40168000) => /lib/ (0x4017c000) => /lib/ (0x4019d000) => /lib/ (0x402ba000)
        /lib/ => /lib/ (0x40000000)

ldd first asks the object file what libs it will need to run, then for each of those asks the operating system where it plans on finding them.


Now, a properly built shared object (in ELF format, which is the format GNU/Linux uses) will have a soname built into it. This is a name that is specified at the library's build-time, to GCC's link editor (ld), with the -soname option. You can inspect any sensibly-built library's soname like so:

bash$ objdump -p /usr/X11R6/lib/ | grep SONAME   

In this case,'s soname is "". The point of the soname is for the creator of the library to be able to provide version compatibility information to the system. In this case,'s soname says that is compatible with any program that says it needs

Programs know what libs they need to link to at runtime -- they know the soname's they want. When an OpenGL program starts up and asks the system for, the system delivers

link editing

Note, when you link a program that requires, you specify -lFoo as an option to the link editor on the gcc or g++ command line. What's going on at build-time is:

  • you tell gcc/g++ you want to set things up so your app links to at runtime.
  • after compiling, at link-time, gcc/g++ passes this information to its link editor ld
  • ld pokes around in /lib, /usr/lib, and anywhere else you specified for it to look using the -L gcc/g++ option; and then comes up with, say,
    • If you have multiple incompatible's on your system (say, for example and, either be sure to use the -L option, or else specify the lib's location explicitly (as in /usr/local/lib/ (note, no -l option is needed here)).
  • Your app links to this specific version of, and has's soname string embedded into itself.

A final note: if you are writing your own shared library, remember to properly use the -soname option (for example,


Shared libs have symlinks with names differing only by version number: --> --> --> ../X11R6/lib/

The user doesn't make these links manually. Rather, the program /sbin/ldconfig takes care of it for us. When you run ldconfig it does for us the following:

  • It searches through /lib, /usr/lib, and all the directories listed in /etc/ looking for shared objects.
  • For all the libs in the directories listed in /etc/, it takes note of their sonames.
  • It then updates /etc/ with this information.
  • Using, it creates symlinks: pointing from the soname named symlink to the actual lib. ldconfig only creates one symbolic link that is based on SONAME of a shared library. This is verified with glibc-2.4-31.2 on SUSE Linux Enterprise Desktop 10 (i586) VERSION = 10 and glibc-2.2.4-31.7 on Red Hat Enterprise Linux WS release 2.1 (Tampa).
  • As far as base name symbolic link creation is concerned, that is created by the library creater if the library is meant for program development. The base name shared library symbolic link is only required at the time of program compilation. One can verify this fact. As all of us know that to access sin() and cos() math functions we need to include the math library (passing -lm to gcc/g++). The required math library's shared symbolic link is /usr/lib/ this points to /lib/ is the SONAME symbolic link of the original math library /lib/ Here /lib/ file is created by ldconfig. Now give the following command rpm -qf /usr/lib/ The out put will be something like this glibc-devel-2.4-31.2 (this is on my machine. You may have different version of glibc-devel name.). The glibc-devel is required for program development.

Loading shared libs at runtime

When you run a program, a series of events happen culminating in the app being loaded into memory as well as any shared objects the program needs which weren't already loaded. Here's a walkthrough of those events:

  • You execute the program.
  • The OS's dynamic linker, (yes, it's a funny name for an executable), checks the executable to see which shared libs it needs, thus discovering the sonames of the needed libs.
  • With sonames in-hand, consults to find out the locations of the shared lib files it needs to load into memory.
  • loads the required libs, and then the program is allowed to execute.

Of course, if you had 2 incompatible versions of on your system -- say, and -- each would have a different soname: "" and "". As such, ldconfig and would be able to tell the difference between the two, and you could have them both installed on your system simultaneously. That is, applications that depend on "" being installed would always get the right one at runtime.

Creating your own libraries

Shared libraries

This is an example how you get your own dynamic linked library and a program that uses it. The only thing you will need to is to install gcc:

cat > main.cpp << EOF
#include <iostream>
#include <dlfcn.h> 

extern "C" void help(); 

int main() 
  return 0;

We have now created your main program. It contains a declaration of the function help(), but no implementation. The program does nothing more than to call the function help(), notably, without knowing about its implementation.

cat > help.cpp << EOF
#include <iostream>

extern "C" void help() 
  std::cout << "hello world" << '\n';

We have now created your library. It implements the function help().

gcc help.cpp -o -ldl -shared -fPIC

We have now built your library,

g++ main.cpp -lhelp

Now we have built an executable a.out that uses a library This looks for me like this:

tweedleburg:~/test # ldd a.out =>  (0x00007fff6dffe000) => not found => /usr/lib64/ (0x00007fec65a02000) => /lib64/ (0x00007fec657ac000) => /lib64/ (0x00007fec65595000) => /lib64/ (0x00007fec6523c000)
        /lib64/ (0x00007fec65d0e000)

Of course we cannot get it running:

tweedleburg:~/test # ./a.out
./a.out: error while loading shared libraries: cannot open shared object file: No such file or directory

Without the correct path to search the libraries:

tweedleburg:~/test # export LD_LIBRARY_PATH=.
tweedleburg:~/test # ./a.out
hello world

Static libraries

For a static library (or "archive"):

ar -r libFooBar.a foo.o bar.o
gcc -o your_app main.o libFooBar.a

See also