View the Most Wanted LQ Wiki articles.
LinuxQuestions.org > Linux Wiki > Library-related Commands and Files

From LQWiki

Jump to: navigation, search

A software developer can write code that doesn't necessarily compile into a standalone program. Instead, a source code file (or a related group of files) can be compiled into a reusable compartmentalized module called a library. A given library is one file, for example: /usr/lib/libSDL-1.2.so.0.0.4. Here's what the file command has to say about that particular library on my system:

bash$ file /usr/lib/libSDL-1.2.so.0.0.4
/usr/lib/libSDL-1.2.so.0.0.4: ELF 32-bit LSB shared object,
    Intel 80386, version 1 (SYSV), stripped

Elsewhere, when another software developer wants to create an executable program, they almost never write the whole thing themselves -- they leverage existing ready-to-use libraries and link their code to the already-built library.

A program can be linked to a library forming one big executable, but that wastes disk space and memory since many programs on the same system might want to use the same library. That's called static linking and is only used very sparingly these days. For example, static linking might be used if some program uses a heavily modified library that it specifically requires but that no other programs would want to use. Libraries used this way are called static libraries and have the .a filename extension. (Another use of static linked programs is in setting up LFS. At first, LFS doesn't have any libraries to link to, so static executables are used as a toolchain to bootstrap the process. These static executables are later replaced with dynamically linked executables.)

The modern and customary way to use libraries is for a program to request (from the operating system) a library (or libraries) when the program starts up -- that is, at runtime. Then, the program's code dynamically links to the library code right then-and-there just when it needs the library. These types of libraries are referred to as "dynamically linked libraries" or "shared libraries". On GNU/Linux, we sometimes call them shared objects, since their file names have the extension .so (usually plus some version numbers). On MS Windows they're called "DLL's". On Mac OS X, shared lib filenames end in .dylib.

The rest of this article discusses how a program gets linked to the shared objects it needs at runtime, and the various system executables and files that make this possible.


Contents

Shared Libraries

Naming conventions

Shared libraries have names like libGL.so.1.2. In this example, that's the library which implements OpenGL on my Debian "stable" system. It's located in /usr/X11R6/lib, but there is a link to it in /usr/lib, along with some other symlinks:

libGL.so --> libGL.so.1.2
libGL.so.1 --> libGL.so.1.2
libGL.so.1.2 --> ../X11R6/lib/libGL.so.1.2

The "1" indicates major revision 1, and "2" indicates minor revision 2. All libraries with the same major revision number should present the same API to users of that library -- that is, if you can compile your code against libFoo.so.2.4, you should be able to compile it against libFoo.so.2.32 without any changes. Changes in major revision number indicate a change in the external interface presented to users of that library. Changes in minor revision number indicate bug fixes. :)

ldd

You can easily find out which shared libs a given app (or even another shared lib) requires using the ldd command. For example, for the glxgears program:

bash$ ldd /usr/X11R6/bin/glxgears
        libGL.so.1 => /usr/X11R6/lib/libGL.so.1 (0x4001a000)
        libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x40080000)
        libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x4008e000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x40168000)
        libm.so.6 => /lib/libm.so.6 (0x4017c000)
        libc.so.6 => /lib/libc.so.6 (0x4019d000)
        libdl.so.2 => /lib/libdl.so.2 (0x402ba000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (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.

nm

Nm tells you the names of the symbols in a binary file.

soname

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/libGL.so.1.2 | grep SONAME   
 SONAME      libGL.so.1

In this case, libGL.so.1.2's soname is "libGL.so.1". 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, libGL.so.1.2's soname says that libGL.so.1.2 is compatible with any program that says it needs libGL.so.1.

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 libGL.so.1, the system delivers libGL.so.1.2. (Recall, this is on my system. Your system may (I would hope :) have a more recent version of OpenGL installed.)

link editing -- for programmers only

This subsection is just some more background info for programmers. Users may skip it.

Note, when you link a program that requires libFoo.so, 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 libFoo.so 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, libFoo.so.1.22.
    • If you have multiple incompatible libFoo.so's on your system (say, for example libFoo.so.1.22 and libFoo.so.2.0.1), either be sure to use the -L option, or else specify the lib's location explicitly (as in /usr/local/lib/libFoo.so.2.0.1 (note, no -l option is needed here)).
  • Your app links to this specific version of libFoo.so, and has libFoo.so's soname string embedded into itself. The reason for this will be obvious in a moment (keep reading :).

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

ldconfig

Above, we noted how shared libs have symlinks with names differing only by version number:

libGL.so --> libGL.so.1.2
libGL.so.1 --> libGL.so.1.2
libGL.so.1.2 --> ../X11R6/lib/libGL.so.1.2

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/ld.so.conf looking for shared objects.
  • For all the libs in the directories listed in ld.so.conf, it takes note of their sonames.
  • It then updates /etc/ld.so.cache with this information.
  • Using ld.so.cache, 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/libm.so this points to /lib/libm.so.6(this is the SONAME symbolic link of the original math library /lib/libm-2.4.so). Here /lib/libm.so.6 file is created by ldconfig. Now give the following command rpm -qf /usr/lib/libm.so. The out put will be something like this glibc-devel-2.4-31.2 (this is on my machine. You may have diffrent 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, ld.so (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, ld.so consults ld.so.cache to find out the locations of the shared lib files it needs to load into memory.
  • ld.so loads the required libs, and then the program is allowed to execute.

Of course, if you had 2 incompatible versions of libFoo.so on your system -- say, libFoo.so.1.4 and libFoo.so.2.0.1 -- each would have a different soname: "libFoo.so.1" and "libFoo.so.2". As such, ldconfig and ld.so 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 "libFoo.so" being installed would always get the right one at runtime.


Manually adding shared libs to your system

Debian users can safely skip this section. ;) If you properly install a debian package using a tool like apt-get, any required configuration is taken care of for you. Of course, on the other hand, if you are creating a package yourself you'll need to be doing the configuration for your users, as part of the install script. :)

If you do need to install your shared libs by-hand:

  • Copy the library to where it belongs (maybe /usr/local/lib or /home/username/lib).
  • Make sure ld.so.conf contains the name of the directory where you placed the library.
  • Run ldconfig as root.

Creating your own libraries

If you're a programmer and want to create your own library (from, say, files foo.c and bar.c -- and maybe link it to some main.o), the compiler and linker commands you're looking to put into your makefile are:

  • For a shared library:
gcc -fPIC -c foo.c bar.c
gcc -shared -o libFooBar.so.1.2 -Wl,-soname="libFooBar.so.1" foo.o bar.o
gcc -o your_app main.o -L. -lFooBar
(Replace "gcc" with "g++" if it's a C++ lib you're building.)
  • For a static library (or "archive"):
ar -r libFooBar.a foo.o bar.o
gcc -o your_app main.o libFooBar.a

See Also: C, libtool, nm, objdump, Programming-related_Commands


External links


Personal tools