Author: Mugabi Siro
Category: ELF Support
A tutorial on generating and using static libraries on a GNU/Linux system. The C language is mainly assumed. Development platform used was Ubuntu 12.04 AMD64.Tags: gnu/linux toolchain gnu linux s/w development elf support libraries
Refer to ELF Object File Types for a background on ELF object file types supported on a GNU/Linux system.
A static library file is an archive of concatenated relocatable object files. It features a header that describes the size and location of each
relocatable object file member. Each relocatable (
.o) corresponds to a
C source file (
.c) module which, typically, defines one or a few related
functions and variables. These archive files conventionally have the
.a extension and are generated via the GNU Archiver,
In contrast, combining all the C modules into a single source file to generate a monolithic relocatable object file, and then directly linking programs against it - instead of using an archive of separate relocatables - has a number of disadvantages. Notably, any program linked against the monolithic relocatable will always include its entire bloat, regardless of whether the program only references symbols that are contained in a few of the C modules of the monolithic relocatable's single source file. On the other hand, using an archive will result in a final program that only includes the set of member relocatables that define the referenced symbols.
This is a two step procedure:
Generate the relocatable object file members e.g:
$ gcc -Wall -O2 -c foo1.c foo2.c foo3.c ...
Generate the archive file, e.g:
$ ar rcs libfoo.a foo1.o foo2.o foo3.o ...
rinsert the files listed into the archive, replacing any matching and pre-existing members.
ccreate the archive if it didn't exist
sadd an, or update the, archive index
ar(1) for more details on usage and available options.
A general rule with
ld(1)) command line when linking against libraries is: the object file or library which contains definitions of exported symbols must be specified after any other files which reference those symbols.
So, for example, if
libfoo.a contains references to symbols defined
libbar.a, then the command line will resemble:
$ gcc -Wall -O2 prog.c libfoo.a libbar.a
Sometimes, circular references may exist between archives such that, say,
libbar1.a contains references to symbols defined in
libbar2.a also contains references to symbols defined in
libbar1.a. In this case:
$ gcc -Wall -O2 prog.c libbar1.a libbar2.a libbar1.a
$ gcc -Wall -O2 prog.c -Wl,--start-group libbar1.a libbar2.a -Wl,--end-group
However, note that this second approach can incur significant build time
since the archives are searched repeatedly until all possible references are
gcc(1) linker options,
-l, may also be used accordingly when linking against static libraries e.g.
$ gcc -Wall -O2 prog.c -Wl,--start-group -L . -lbar1 -lbar2 -Wl,--end-group
Static libraries allow the generation of statically linked executables. Generally, shared libraries hold information suitable only for dynamically linked object files and (conventionally) cannot be used for building statically linked executables. Standard GNU/Linux toolchain installations1 include both shared and static library versions e.g:
$ locate libc.so.6 /lib/x86_64-linux-gnu/libc.so.6 /lib32/libc.so.6 /usr/arm-linux-gnueabi/lib/libc.so.6 /usr/arm-linux-gnueabihf/lib/libc.so.6 $ locate libc.a /usr/arm-linux-gnueabi/lib/libc.a /usr/arm-linux-gnueabihf/lib/libc.a /usr/lib/x86_64-linux-gnu/libc.a /usr/lib32/libc.a
gcc(1) will generate a dynamically linked executable against
the shared library versions. To build a statically linked
executable, specify the
-static switch e.g:
$ gcc -Wall -O2 -static prog.c $ file a.out a.out: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, ...
An attempt to explicitly link against a shared library version when building a statically linked executable will fail, for instance:
$ gcc -Wall -O2 -static prog.c libfoobar.so /usr/bin/ld: attempted static link of dynamic object `libfoobar.so' collect2: ld returned 1 exit status
Recall that shared objects contain code only suitable for use with dynamically linked object files.
As an exercise, perform the following static library and statically linked executable
build and test with the
fooprog.c sources in
the Shared Library Tutorial entry:
$ gcc -Wall -O2 -c libfoo.c $ ar rcs libfoo.a libfoo.o $ gcc -Wall -O2 -static fooprog.c libfoo.a $ file a.out a.out: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked ... $ ./a.out libfoo
Note that it is generally possible to mix static and shared libraries
gcc(1) command line when building dynamically linked executables:
$ gcc -Wall -O2 fooprog.c libfoo.a ## no "-static" so "gcc(1)" pulls in "libc.so" shared lib by default $ file a.out a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs) ... $ ./a.out libfoo