MkLinux Shared Library Support


Document Change History (check here to see what's different if you've visited this page before)

Introduction

Shared library support for MkLinux (actually, all Linux/PowerPC systems) has recently become available, due largely to work by Gary Thomas (based on work from Cygnus Solutions). This document describes the steps you need to follow to set up shared libraries on a MkLinux system. The information here was gleaned from several sources, such as the shared library section of Jon Howell's FAQ-O-Matic, the README from Chris Penney's shared X11R6.3 distribution, and the MkLinux mailing lists.

A big thanks to Gary Thomas for reviewing an early draft of this document and providing several corrections and clarifications. Any remaining errors are mine; if you find mistakes or have additional information to contribute, please let me know.

Philippe Laliberte contributed the Netscape helper settings and the list of RPMs that is mentioned in this document.

Kevin Hendricks sent me some comments about his experience installing shared libraries. You can read his remarks here.

Why Use Shared Libraries?

The primary reason to use shared libraries is that you achieve a reduction in disk and memory use.

With a static library, a copy of the library's code is linked into every program that uses it. When a library is shared, programs that use it contain only references to library routines. The references are resolved by the runtime link editor when programs begin execution. All shared executables reference the same copy of the library, which then need not be included in executable images stored on disk. As a result, shared executables are smaller than static executables -- sometimes dramatically so. For example, an unshared version of xterm has copies of the X libraries linked into it, and is 1411KB in size. The shared version is only 155KB in size.

In addition, shared libraries reduce memory use. Since a static library is included as part of the calling program's image, a copy is loaded into the process space of each running program that uses it. For a shared library, a single copy suffices; the same copy is referenced by each shared executable that uses the library. Suppose you run a window manager and xterm, both of which use X libraries. With static executables, you'll have two copies of the libraries in memory. With shared executables, you'll have only one.

Another advantage of shared libraries is that when a library is updated, e.g., to fix a bug, all programs which use the library immediately enjoy the fix, without have to be rebuilt. (Or course, there is a corresponding danger: if you introduce a bug into a shared library, all programs that use the library become subject to the bug.)

The disk and memory savings of shared libraries is offset by a slight performance penalty when a shared executable starts up. References to shared library routines must be resolved by finding the libraries containing those routines. However, references need be resolved only once, so the performance penalty is quite small.

Runtime link editing is done by /lib/ld.so ("so" = "shared object"). The linker's performance can be improved by generating a cache file /etc/ld.so.cache that enumerates the locations of the shared libraries available on your system. This way the link editor needn't search your system for libraries each time you run a shared executable. Cache file generation is covered below.

Support File Locations

The main repository for shared library support is ftp.linuxppc.org. The directories listed below are of special interest. The files you'll find there are provided in the form of RPM (Red Hat Package Manager) files, so make sure you have a current version of the rpm program. (The one from the DR2.1 distribution worked for me.)

RPMs that require shared libraries can be identified by the convention that their names have an upper case letter as part of the revision number, e.g. "abc-1.0.1A.ppc.rpm".

Where I show RPM filenames below, they are the ones I installed. If newer versions are available, you should probably install those instead.

Preliminaries

If you're thinking about installing shared library support, be aware that shared libraries on MkLinux require DR2.1 or newer kernels. In general, it's a good idea to be running the latest MkLinux kernel and server. My system is currently running MkLinux DR2.1, Update 1.

Before you begin, you should backup your system if at all possible.

As indicated by the "#" prompt, most of the commands shown below must be executed as root.

Basic Shared Library Support

To take advantage of the benefits of shared libraries, you must install the libraries themselves, the runtime link editor, shared versions of executable programs, and the ldconfig program. You must also create the runtime linker's cache file, /etc/ld.so.cache.

Shared Library RPMs

The glibc RPMs contain the runtime link editor, the most important shared libraries, and shared executables for several programs that use them. These RPMs are:

    glibc-0.961212-1I.ppc.rpm
    glibc-static-0.961212-1I.ppc.rpm
    glibc-devel-0.961212-1I.ppc.rpm
    glibc-info-0.961212-1I.ppc.rpm

The first glibc RPM contains the shared library runtime link editor /lib/ld.so, several shared libraries, related utilities (such as ldd, a program that displays the shared libraries a program uses), and shared executable versions of a few programs. The second RPM contains static versions of the shared libraries. The other two RPMs contain header and info files.

You should also get the shared termcap RPMs from the archive, since the termcap library is used by many programs:

    libtermcap-2.0.8-2A.ppc.rpm
    libtermcap-devel-2.0.8-2A.ppc.rpm

Get the RPMs listed above from the archive and install them using this command:

    # rpm -i --force --nodeps glibc* libtermcap*

The -i option tells rpm to install the named packages. If you want to see what's going on as rpm runs, use -ih instead to make rpm display hash marks (#) as progress indicators. -ihv runs rpm in verbose mode for even more feedback.

The --force and --nodeps options tell rpm to install files even if they replace older ones and not to check for package dependencies.

Another good candidate for installation is the ncurses library. You may not need it immediately, but it's not a bad idea to install it now since you'll probably run into packages that require it soon enough. The RPMs are:

    ncurses-1.9.6-6A.ppc.rpm
    ncurses-devel-1.9.6-6A.ppc.rpm

Install the RPMs like this if you get them:

    # rpm -i --force --nodeps ncurses*

ldconfig and the Cache File /etc/ld.so.cache

After you've installed the basic set of shared libraries and executables, you can install the ldconfig program and construct the cache file used by ld.so, the runtime link editor. The cache file lists which shared libraries are available on your system. This improves the performance of ld.so since it doesn't have to search directories each time a shared executable starts up.

Get the ldconfig RPM from the archive and install it:

    # rpm -i --force --nodeps ldconfig-1.8.1-3A.ppc.rpm

This installs ldconfig as /sbin/ldconfig.

Now create /etc/ld.so.conf, a file used by ldconfig to determine what directories to look in to find shared libraries when it builds the cache file. The file can be created with the following contents:

    /lib
    /usr/lib
    /usr/X11/lib
    /usr/local/lib

If you have shared libraries in any other directories, list those in /etc/ld.so.conf, too.

It's not really necessary to list /lib and /usr/lib in /etc/ld.so.conf, because ldconfig searches those directories anyway. On the other hand, it doesn't hurt to list them, and it makes those locations explicit for anyone who happens to look at the file.

After you create /etc/ld.so.conf, run ldconfig as root to build the cache file /etc/ld.so.cache:

    # ldconfig

If you want ldconfig to tell you what it's doing, run it in verbose mode:

    # ldconfig -v
    ldconfig: version 1.8.1
    /lib:
        libtermcap.so.2 => libtermcap.so.2.0.8
        libutil.so.1 => libutil.so.1
        libresolv.so.2 => libresolv.so.2
        libpthread.so.0 => libpthread.so.0
    etc.

If you want to verify what's in the cache, run this command:

    # ldconfig -p
    87 libs found in cache `/etc/ld.so.cache' (version 1.7.0)
         1 - ELF libutil.so.1 => /lib/libutil.so.1
         2 - ELF libutil.so.1 => /lib/libutil.so.1
         3 - ELF libutil.so.1 => /lib/libutil-1.99.so
         4 - ELF libutil.so.1 => /lib/libutil-1.99.so
         5 - ELF libtermcap.so.2 => /lib/libtermcap.so.2.0.8
         6 - ELF libtermcap.so.2 => /lib/libtermcap.so.2.0.8
    etc.

After you install the RPMs listed above and generate the cache file, you should reboot:

    # shutdown -r now

You should rerun ldconfig whenever you install new shared libraries. Otherwise the cache file will be inaccurate and the runtime link editor may not properly resolve references to shared library routines.

If you've used ldconfig on other systems, note that it doesn't necessarily work the same way on MkLinux, and the command-line arguments may be different. For instance, the option to display the contents of the cache file is -r for FreeBSD, but -p for MkLinux.

Another way to help the linker ld.so find shared libraries on a session-specific basis is to set the LD_LIBRARY_PATH environment variable in one of your shell's startup files (e.g., .login for csh/tcsh or .bash_profile for bash).

The value of LD_LIBRARY_PATH is a colon-separated list of directories. csh/tcsh users can set it as follows:

    setenv LD_LIBRARY_PATH lib:/usr/lib:/usr/X11/lib:/usr/local/lib

bash users can set it like this instead:

    export LD_LIBRARY_PATH
    LD_LIBRARY_PATH=lib:/usr/lib:/usr/X11/lib:/usr/local/lib

However, for security reasons, LD_LIBRARY_PATH is ignored for setuid/setgid programs.

Using ldd

One of the utilities installed by the glibc RPMs is the ldd (list dynamic dependencies) program. ldd examines a file and displays the shared libraries the program depends on. If a file isn't a shared executable, ldd says so:

    # ldd /sbin/ldconfig
            not a dynamic executable

Otherwise, ldd lists the shared libraries required by the program:

    # ldd /bin/bash
        libtermcap.so.2 => /lib/libtermcap.so.2.0.8 (0x2aaac000)
        libc.so.6 => /lib/libc.so.6 (0x2aaf1000)
        /lib/ld.so.1 => /lib/ld.so.1 (0x00000000)

The output from ldd can be useful for determining whether or not you have the version of a shared library that a shared executable needs. (More than one version of a library can be installed simultaneously on your system.)

Compiler Support

Installing shared library support as described above breaks the standard compiler setup. To get it working again, install these RPMs:

    gcc-2.7.2-2G.ppc.rpm
    gcc-c++-2.7.2-2G.ppc.rpm
    binutils-2.7-1D.ppc.rpm
    kernel-headers-2.0.28-1B.ppc.rpm
    libg++-2.7.1.4-4E.ppc.rpm
    libg++-devel-2.7.1.4-4E.ppc.rpm

Remember to run ldconfig again after installing the RPM files.

Shared X11 Support

The shared X11R6.3 distribution is available from Chris Penney. A file README.sharedlibs is also available at his site that describes what you need to do to make the distribution work. I'll just summarize that information here. You need to install basic shared library support as described above. In addition, you need the gdbm RPM:

    # rpm -i --force --nodeps gdbm-1.7.3-8A.ppc.rpm

Remember to run ldconfig again after installing the gdbm RPM.

It's well worth getting the shared X11 distribution for the savings in disk space alone. The static distribution takes about 90MB, whereas the shared distribution takes only about 30MB.

Shared rpm

If you get an RPM file that needs to be installed with a newer version of rpm than the one you have, get the current rpm RPMs from the archive and install them. The RPMs are:

    rpm-2.3-1A.ppc.rpm
    rpm-devel-2.3-1A.ppc.rpm

However, before you get these, be sure you've installed shared library support. The version of rpm that these install uses shared libraries, and if you install it without having shared library support, you'll no longer have a working rpm.

Install the RPMs like this:

    # rpm -i --force --nodeps rpm*

You may also need to reinitialize the RPM database. The symptom of this is that rpm prints error messages about not being able to open files in the /var/lib/rpm directory. This is because some of the internal database structures have changed. To deal with this, remove the existing files and reinitialize the database:

    # rm -f /var/lib/rpm/*
    # rpm --initdb

Problems

Various programs stop working after you install shared libraries. These include last, who, w, update, top, and finger.

You may be able to fix who by installing a new util-linux RPM (this actually fixes /bin/login, which generates information used by who), and a new sh-utils RPM (which contains an updated who). To install the util-linux RPM, you'll also need the pam (Pluggable Access Module) RPMs. pam is a security module. It's not yet fully supported by Linux/PPC, but is required to install some packages. The RPMs are:

    pam-0.54-4A.ppc.rpm
    pamconfig-0.50-5A.ppc.rpm
    util-linux-2.5-33A.ppc.rpm
    sh-utils-1.12-4A.src.rpm

You may be able to fix last by installing a new SysVInit RPM. The RPM is:

    SysVinit-2.62-1A.ppc.rpm

You'll probably have a problem doing a shutdown after you install this RPM, because some of the programs involved in the process will have been changed. You may have to force-restart your machine.

finger can be fixed by installing a new NetKit RPM:

    NetKit-B-0.08-13B.ppc.rpm

Note that the NetKit RPM installs some shared binaries (such as in.telnetd) that depend on the shared ncurses library, so you should also get that.

w, uptime, and top can be fixed by installing a new procps RPM:

    procps-1.01-5B.ppc.rpm

List of RPMs Mentioned in This Document

RPMs that are mentioned for downloading in this document are listed below. If you have not yet done so, you should add the following helper to your Netscape settings (assuming you use Netscape):

Specify the option of "save to disk".

Change History

2 April 1997


Document written by: Paul DuBois, paul@snake.net
Last updated: Saturday, 12 April 1997 17:58