Having covered the basics of compilation and linking, the next
important point for a C Programmer is understanding the libraries. To give an
example of library, the printf function in the basic Hello World program comes
from the standard Libc library.
So what makes a Library?. To put in plain
words, a library is a file containing several object files, that can be used as
a single entity in a linking phase of a program. Linux system allows us to
create and use two kinds of libraries - static libraries and
shared (or dynamic) libraries. In part 1 we will
discuss the static libraries, and part 2 will cover the shared libraries.
Static Library:
Libraries that are typically stored in special archive files with
the extension ‘.a’, are 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; as
discussed in earlier blog.
In Linux, the standard system libraries are usually found in the
directories ‘/usr/lib’ and ‘/lib’. For example, the C math
library is typically stored in the file‘/usr/lib/libm.a’ . 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.
The basic tool used to create static libraries is a program
called 'ar', for 'archiver'. This
program can be used to create static libraries, modify object files in the
static library, list the names of object files in the library, and so on.
In order to create a static library, the command is like
this:
$ ar rc libutil.a util_X.o util_Y.o util_Z.o
This command creates a static library named 'libutil.a' and puts
copies of the object files "util_X.o", "util_Y.o" and
"util_Z.o" in it. If the library file already exists, it has the
object files added to it, or replaced, if they are newer than those inside the
library. The 'c' flag tells ar to create the library if it doesn't
already exist. The 'r' flag tells it to replace older object files in
the library, with the new object files.
Library Naming Convention
Libraries are typically named with the prefix "lib".
This is true for all the C standard libraries. When linking, the command line
reference to the library will not contain the library prefix or suffix.
After an archive is created, or modified, there is a need to index
it. This index is later used by the compiler to speed up symbol-lookup inside
the library, and to make sure that the order of the symbols in the library
won't matter during compilation.
Many of us might have encountered compilers complaining that ‘index
is out of date for some library and abort’. If any of your compilers still
issues this warning, you have two options to solve it. The first is to use
ranlib and re-generate the index. The second one is to use 'cp -p', instead of
only 'cp'. The '-p' flag tells 'cp' to keep all
attributes of the file, including its access permissions, owner (if
"cp" is invoked by a superuser) and its last modification date. This
will cause the compiler to think the index inside the file is still updated. This
method is useful for makefiles that need to copy the library to another
directory for some reason.
Note: Ranlib is now embedded into ‘ar’ command in most
modern compilers. Running ranlib is completely equivalent to
executing ar -s.
For listing the index, you may use nm -s or nm
--print-armap.
An archive with such an index speeds up linking to the library and
allows routines in the library to call each other without regard to their
placement in the archive.
Using A "C" Library In A Program
After we created our archive, we want to use it in a program. This
is done by adding the library's name to the list of object file names given to
the linker, using a special flag, normally '-l'. Here
is an example:
$ cc main.o -L. -lutil -o prog
This will create a program using object file "main.o",
and any symbols it requires from the "util" static library. Note
that we omitted the "lib" prefix and the ".a" suffix when
mentioning the library on the link command. The linker attaches
these parts back to the name of the library to create a name of a file to look
for. Note also the usage of the '-L' flag - this flag tells the
linker that libraries might be found in the given directory ('.', referring to
the current directory), in addition to the standard locations where the
compiler looks for system libraries.
I hope you guys had a good time with static libraries. In part 2,
we will discuss about shared / dynamic libraries.