### 2.7 Linking with external libraries ¶

A library is a collection of precompiled object files which can be linked into programs. The most common use of libraries is to provide system functions, such as the square root function `sqrt` found in the C math library.

Libraries are typically stored in special archive files with the extension `.a`, referred to as static libraries. They are created from object files with a separate tool, the GNU archiver `ar`, and used by the linker to resolve references to functions at compile-time. We will see later how to create libraries using the `ar` command (see Compiler-related tools). For simplicity, only static libraries are covered in this section—dynamic linking at runtime using shared libraries will be described in the next chapter.

The standard system libraries are usually found in the directories `/usr/lib` and `/lib`.5 For example, the C math library is typically stored in the file `/usr/lib/libm.so` on Unix-like systems. The corresponding prototype declarations for the functions in this library are given in the header file `/usr/include/math.h`. The C standard library itself is stored in `/usr/lib/libc.a` and contains functions specified in the ANSI/ISO C standard, such as ‘`printf`’—this library is linked by default for every C program.

Here is an example program which makes a call to the external function `sqrt` in the math library `libm.a`:

    #include <math.h>
    #include <stdio.h>

    int
    main (void)
    {
      double x = sqrt (2.0);
      printf ("The square root of 2.0 is %f\n", x);
      return 0;
    }

Trying to create an executable from this source file alone causes the compiler to give an error at the link stage:

    $ gcc -Wall calc.c -o calc
    /tmp/ccbR6Ojm.o: In function `main':
    /tmp/ccbR6Ojm.o(.text+0x19): undefined reference
      to `sqrt'

The problem is that the reference to the `sqrt` function cannot be resolved without the external math library `libm.a`. The function `sqrt` is not defined in the program or the default library `libc.a`, and the compiler does not link to the file `libm.a` unless it is explicitly selected. Incidentally, the file mentioned in the error message `/tmp/ccbR60jm.o` is a temporary object file created by the compiler from `calc.c`, in order to carry out the linking process.

To enable the compiler to link the `sqrt` function to the main program `calc.c` we need to supply the library `libm.a`. One obvious but cumbersome way to do this is to specify it explicitly on the command line:

    $ gcc -Wall calc.c /usr/lib/libm.a -o calc

The library `libm.a` contains object files for all the mathematical functions, such as `sin`, `cos`, `exp`, `log` and `sqrt`. The linker searches through these to find the object file containing the `sqrt` function.

Once the object file for the `sqrt` function has been found, the main program can be linked and a complete executable produced:

    $ ./calc
    The square root of 2.0 is 1.414214

The executable file includes the machine code for the main function and the machine code for the `sqrt` function, copied from the corresponding object file in the library `libm.a`.

To avoid the need to specify long paths on the command line, the compiler provides a short-cut option ‘`-l`’ for linking against libraries. For example, the following command,

    $ gcc -Wall calc.c -lm -o calc

is equivalent to the original command above using the full library name `/usr/lib/libm.a`.

In general, the compiler option `-lNAME` will attempt to link object files with a library file `libNAME.a` in the standard library directories. Additional directories can specified with command-line options and environment variables, to be discussed shortly. A large program will typically use many `-l` options to link libraries such as the math library, graphics libraries and networking libraries.

#### Footnotes

##### (5)

On systems supporting both 64 and 32-bit executables, their libraries are stored in the directories `/lib/x86_64-linux-gnu` and `/usr/lib/x86_64-linux-gnu`, or `/lib64` and `/usr/lib64` for 64-bit libraries; and `/lib/i386-linux-gnu` and `/usr/lib/i386-linux-gnu`, or `/lib` and `/usr/lib` for 32-bit libraries, instead. see Multi-architecture support