Back Contents Next

Library Files

Libraries are collections of precompiled functions that have been written to be reusable. Typically, they consist of sets of related functions to perform a common task. Examples include libraries of screen handling functions (the curses library) and database access routines (the dbm library). We'll meet these libraries in later chapters.

 

Standard system libraries are usually stored in /lib and /usr/lib. The C compiler (or more exactly, the linker) needs to be told which libraries to search, as, by default, it searches only the standard C library. This is a remnant of the days when computers were slow and CPU cycles expensive. It's not enough to put a library in the standard directory and hope the compiler will find it; libraries need to follow a very specific naming convention and need to be mentioned on the command line.

 

A library name always starts with lib. Then follows the part indicating what library this is (like c for the C library, or m for the mathematical library). The last part of the name starts with a dot ., and specifies the type of the library:

Ø .a for traditional, static libraries

Ø .so and .sa for shared libraries (see below)

 

Usually, the libraries exist in both static and shared formats, as a quick ls /usr/lib will show. You can instruct the compiler to search a library either by giving it the full path name or by using the -l flag. For example,

 

$ cc -o fred fred.c /usr/lib/libm.a

 

tells the compiler to compile file fred.c, call the resulting program file fred and search the mathematical library in addition to the standard C library to resolve references to functions. A similar result is achieved through:

 

$ cc -o fred fred.c -lm

 

The -lm (no space between the l and the m) is shorthand (shorthand is much valued in UNIX circles) for the library called libm.a in one of the standard library directories (in this case
/usr/lib
). An additional advantage of the -lm notation is that the compiler will automatically choose the shared library when it exists.

 

Although libraries usually are found in standard places in the same way as header files, we can add to the search directories by using the -L (notice the uppercase letter) flag to the compiler. For example,

 

$ cc -o x11fred -L/usr/openwin/lib x11fred.c -lX11

 

will compile and link a program called x11fred using the version of the library libX11 found in the directory /usr/openwin/lib.

 

Static Libraries

The simplest form of library is just a collection of object files kept together in a ready-to-use form. When a program needs to use a function stored in the library, it includes a header file that declares the function. The compiler and linker take care of combining the program code and the library into a single executable program. You must use the –l option to indicate which libraries, other than the standard C runtime library, are required.

 

Static libraries, also known as archives, conventionally have names that end with .a. Examples are /usr/lib/libc.a and /usr/X11/lib/libX11.a for the standard C library and the X11 library.

 

We can create and maintain our own static libraries very easily by using the ar (for archive) program and compiling functions separately with cc -c. You should try to keep functions in separate source files as much as possible; if functions need access to common data, you can place them in the same source file and use 'static' variables declared in that file.


Try It Out - Static Libraries

1    Let's create our own, small library containing two functions and then use one of them in an example program. The functions are called fred and bill and just print greetings. We'll create separate source files (called, imaginatively, fred.c and bill.c) for each of them.

 

#include <stdio.h>

 

void fred(int arg)

{

    printf("fred: you passed %d\n", arg);

}

 

#include <stdio.h>

 

void bill(char *arg)

{

    printf("bill: you passed %s\n", arg);

}

We can compile these functions individually to produce object files ready for inclusion into a library. We do this by invoking the C compiler with the -c option that prevents the compiler from trying to create a complete program. This would fail because we haven't defined a function called main.

$ cc -c bill.c fred.c

$ ls *.o

bill.o  fred.o

2                Now let's write a program that calls the function bill. First, it's a good idea to create a header file for our library. This will declare the functions in our library and should be included by all programs that wish to use our library.

/*

    This is lib.h. It declares the functions fred and bill for users

*/

 

void bill(char *);

void fred(int);

 

In fact it's a good idea to include the header file in the files fred.c and bill.c too. This will help the compiler pick up any errors.

3                The calling program (program.c) can be very simple. It includes the library header file and calls one of the functions from the library.

 

#include "lib.h"

 

int main()

{

    bill("Hello World");

    exit(0);

}

 

4          We can now compile the program and test it. For now, we'll specify the object files explicitly to the compiler, asking it to compile our file and link it with the previously compiled object module bill.o.

$ cc -c program.c

$ cc -o program program.o bill.o

$ ./program

bill: you passed Hello World

$

5                Now let's create and use a library. We use the ar program to create the archive and add our object files to it. The program is called ar because it creates archives or collections of individual files placed together in one large file. Note that we can also use ar to create archives of files of any type  (like many UNIX utilities, it is a very generic tool).

$ ar crv libfoo.a bill.o fred.o

a - bill.o

a - fred.o

 

The library is created and the two object files added. To use the library successfully, some systems, notably those derived from Berkeley UNIX, require that a table of contents be created for the library. We do this with the ranlib command. This step isn't necessary (but harmless) when, as in Linux, we're using the GNU software development tools.

 

$ ranlib libfoo.a

 

Our library is now ready to use. We can add to the list of files to be used by the compiler to create our program like this:

 

$ cc -o program program.o libfoo.a

$ ./program

bill: you passed Hello World

$

 

We can also use the –l option to access our library, but as it is not in any of the standard places we have to tell the compiler where to find it, by using the –L option, like this:

 

        $ cc –o program program.o –L. –lfoo

 

The –L. option tells the compiler to look in the current directory for libraries. The –lfoo option tells the compiler to use a library called libfoo.a (or a shared library, libfoo.so if one is present).

 

To see which functions are included in an object file, library or executable program, we can use the nm command. If we take a look at program and lib.a, we see that the library contains both fred and bill, but that program contains only bill. When the program is created, it only includes functions from the library that it actually needs. Including the header file, which contains declarations for all of the functions in the library, doesn't cause all of the library to be included in the final program.

 

If you're familiar with MS-DOS or Microsoft Windows software development, there are a number of direct analogies here.

 

Item

UNIX

DOS

Object Module

func.o

FUNC.OBJ

Static Library

lib.a

LIB.LIB

Program

program

PROGRAM.EXE

Shared Libraries

One disadvantage of static libraries is that when we run many programs at the same time and they all use functions from the same library, we may end up with many copies of the same functions in memory and indeed many copies in the program files themselves. This can consume a large amount of valuable memory and disk space.

 

Many UNIX systems support shared libraries that can overcome both of these disadvantages. A complete discussion of shared libraries and their implementation on different systems is beyond the scope of this book, so we'll restrict ourselves to the visible implementation under Linux.

 

Shared libraries are stored in the same places as static libraries, but have a different extension. On a typical Linux system, the shared version of the standard C library is /lib/libc.so.N, where N represents a major version number, currently 6.

 

At the time of writing many Linux distributions were going through a process of updating the versions of both the C/C++ compiler used, and the C library. The example outputs shown below are taken from a Redhat 6.0 distribution using GNU libc 2.1. Your output may differ slightly if you are not using this distribution.

 

When a program uses a shared library, it is linked in such a way that it doesn't contain function code itself, but references to shared code that will be made available at run time. When the resulting program is loaded into memory to be executed, the function references are resolved and calls are made to the shared library, which will be loaded into memory if needed.

 

In this way, the system can arrange for a single copy of a shared library to be used by many applications at once and stored just once on the disk. An additional benefit is that the shared library can be updated independently of the programs that rely on it. Symbolic links from the file /lib/libc.so.6 to the actual library revision (/lib/libc-2.1.1.so. at the time of writing) are used.

 

For Linux systems, the program (the dynamic loader) that takes care of loading shared libraries and resolving client program function references is ld.so or ld-linux.so.2. The additional locations searched for shared libraries are configured in the file /etc/ld.so.conf, which needs to be processed by ldconfig if changed, for example when X11 shared libraries are added.

 

You can see which shared libraries are required by a program by running the utility ldd:

 

$ ldd program

        libc.so.6 => /lib/libc.so.6 (0x4001a000)

        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

 

 

In this case, we see that the standard C library (libc) is shared (.so). Our program requires major Version 6, which is provided in this case by GNU libc version 2.1.1. Other UNIX systems will make similar arrangements for access to shared libraries. Refer to your system documentation for details.

 

In many ways, shared libraries are similar to dynamic-link libraries used under Microsoft Windows. The .so libraries correspond to .DLL files and are required at run time, while the .sa libraries are similar to .LIB files that get included in the program executable.

 

Back Contents Next
©1999 Wrox Press Limited,US and UK.





Sponsored Links

Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map
Jupiterweb networks

internet.comearthweb.comDevx.comClickZ

Search Jupiterweb:

Jupitermedia Corporation has four divisions:
JupiterWeb, JupiterResearch, JupiterEvents, and JupiterImages

Copyright 2004 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Jupitermedia Corporate Info | Newsletters | Tech Jobs | E-mail Offers