Book: LPI Linux Certification in a Nutshell Section: Chapter 14. Linux Installation and Package Management (Topic 2.2)
### 14.4 Objective 4: Manage Shared Libraries When a program is compiled under Linux, many of the functions required by the program are linked from system libraries that handle disks, memory, and other functions. For example, when `printf( )` is used in a program, the programmer doesn't provide the `printf( )` source code, but instead expects that the system already has a library containing such functions. When the compiler needs to link the code for `printf( )`, it can be found in a system library and copied into the executable. A program that contains executable code from these libraries is said to be statically linked because it stands alone, requiring no additional code at runtime. Statically linked programs can have a few liabilities. First, they tend to get large, because they include executables for all of the library functions linked into them. Also, memory is wasted when many different programs running concurrently contain the same library functions. To avoid these problems, many programs are dynamically linked. Such programs utilize the same routines but don't contain the library code. Instead, they are linked into the executable at runtime. This dynamic linking process allows multiple programs to use the same library code in memory and makes executable files smaller. Dynamically linked libraries are shared among many applications and are thus called shared libraries. A full discussion of libraries is beyond the scope of the LPIC Level 1 exams. However, a general understanding of some configuration techniques is required. #### 14.4.1 Shared Library Dependencies Any program that is dynamically linked will require at least a few shared libraries. If the required libraries don't exist or can't be found, the program will fail to run. This could happen, for example, if you attempt to run an application written for the GNOME graphical environment but haven't installed the required GTK+ libraries. Simply installing the correct libraries should eliminate such problems. The ldd utility can be used to determine which libraries are necessary for a particular executable.
ldd |
#### Syntax
    ldd programs
#### Description Display shared libraries required by each of the programs listed on the command line. The results indicate the name of the library and where the library is expected to be in the filesystem. #### Example In Objective 3, a trivial executable called hw was created. Despite its small size, however, hw requires two shared libraries:
    # ldd /home/jdean/hw
    /home/jdean/hw:
         libc.so.6 => /lib/libc.so.6 (0x40018000)
         /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
The bash shell requires three shared libraries:
    # ldd /bin/bash
    /bin/bash:
         libtermcap.so.2 => /lib/libtermcap.so.2 (0x40018000)
         libc.so.6 => /lib/libc.so.6 (0x4001c000)
         /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
#### 14.4.2 Linking Shared Libraries Dynamically linked executables are examined at runtime by the shared object dynamic linker, ld.so. This program looks for dependencies in the executable being loaded and attempts to satisfy any unresolved links to system-shared libraries. If ld.socan't find a specified library, it fails, and the executable won't run. To illustrate this, let's assume that the `printit( )` function from the hw example in Objective 3 is moved to a shared library instead of being compiled into the program. The custom library is called libprintit.so and stored in /usr/local/lib. hw is reconfigured and recompiled to use the new library.[8] By default, ld.sodoesn't expect to look in /usr/local/lib for libraries, and fails to find `printit( )` at runtime: [8] Though not complicated, the compilation of libprintit.so and hw is beyond the scope of the LPIC Level 1 exams.
    # ./hw
    ./hw: error in loading shared libraries: libprintit.so:
       cannot open shared object file: No such file or directory
To find the new library, ld.so must be instructed to look in /usr/local/lib. There are a few ways to do this. One simple way is to add a colon-separated list of directories to the shell environment variable `LD_LIBRARY_PATH`, which will prompt ld.soto look in any directories it finds there. However, this method may not be appropriate for system libraries, because users might not set their `LD_LIBRARY_PATH` correctly. To make the search of /usr/local/lib part of the default behavior for ld.so, files in the new directory must be included in an index of library names and locations. This index is /etc/ld.so.cache. It's a binary file, which means it can be read quickly by ld.so. To add the new library entry to the cache, its directory is first added to the ld.so.conf file, which contains directories to be indexed by the ldconfig utility.
ldconfig |
#### Syntax
    ldconfig [options] lib_dirs
#### Description Update the ld.so cache file with shared libraries specified on the command line in lib_dirs, in trusted directories /usr/lib and /lib, and in the directories found in /etc/ld.so.conf. #### Frequently used options -p Display the contents of the current cache instead of recreating it. -v Verbose mode. Display progress during execution. #### Example 1 Examine the contents of the ld.so library cache:
    # ldconfig -p
    299 libs found in cache `/etc/ld.so.cache' (version 1.7.0)
        libzvt.so.2 (libc6) => /usr/lib/libzvt.so.2
        libz.so.1 (libc6) => /usr/lib/libz.so.1
        libz.so.1 (ELF) => /usr/i486-linux-libc5/lib/libz.so.1
        libz.so (libc6) => /usr/lib/libz.so
        libx11amp.so.0 (libc6) => /usr/X11R6/lib/libx11amp.so.0
        libxml.so.0 (libc6) => /usr/lib/libxml.so.0
    (... listing continues ...)
#### Example 2 Look for a specific library entry in the cache:
    # ldconfig -p | grep "printit"
        libprintit.so (libc6) => /usr/local/lib/libprintit.so
#### Example 3 Rebuild the cache:
    # ldconfig
After /usr/local/lib is added, ld.so.conf might look like this:
    /usr/lib
    /usr/i486-linux-libc5/lib
    /usr/X11R6/lib
    /usr/local/lib
Next, ldconfig is run to include libraries found in /usr/local/lib in /etc/ld.so.cache :
    # ldconfig
    # ./hw
    Hello, world
Now the hw program can execute correctly because ld.so can find libprintit.so in /usr/local/lib. It is important to run ldconfig after any changes in system libraries to be sure that the cache is up-to-date.