Last modified: Jun, 2014
Compiling and assembling convert the high-level source code (such as written in C programming language) to objective code (machine code). However, to make the program executable, external libraries called in the source code have to be included. The process of linking stitches those pieces together and make the final executable. Compiler like GNU Compiler Collection (GCC) can do compiling, assembling and linking all together.
There are generally two types of linking: static linking and dynamic linking. The former links objective code in the compiling time, while the latter does it in run time. The difference will be made clear by examples in the following. Linux environment is assumed.
The example source code for demonstration purpose is as follows:
The working directory is “$HOME/demo”.
Under the working directory, file “test.c” has the content
and “blob1.c” with the content
The file hierachy is like
--demo/ \-- test.c -- my_headers/ \-- blob1.h -- blob1.c
It is obvious that test.c calls a function “print_hello” in “blob1.c”, and “blob.h” is the header file of “blob.c”. Note that “test.c” uses brackets rather than double quotes to include “blob.h”.
Building an executable from the above files is a two-step process
which generates the objective code “blob1.o” under “$HOME/demo/my_headers”.
In the above code, “-I” flag specifies the custom include path (./my_headers) other than the default “/usr/include” and “/usr/local/include” in Linux. The two-line compiling commands can also be consolidated into one line:
Testing the executable with
will print out
If there are many files in the library, such as “blob1.c”, “blob2.c”, …, sharing with an archive can be convenient. Taking the example above, an archive can be created like
Note that the archived library bundle should always be named like “lib
--demo/ \-- test.c \-- my_headers/ \-- blob1.h \-- blob1.c \-- blob1.o \-- my_libs/ \-- libmystuff.a
where the new bundled library archive is placed in another directory other than the previous “my_headers”.
Building an executable is also a two-step process:
The “-L” flag specifies the library path, and “-l” flag specifies the library name according to the naming convention of library archives. Again the one-liner version is
It can be seen that the header files and library files can be placed in different directories. The process still works if “blob1.c” and “blob1.o” in “$HOME/demo/my_headers” are removed.
Dynamic linking links the objective code in run time. The advantage is that different modules of an executable can be updated separately as long as the interfaces among them don’t change. In Linux, those dynamic libraries are usually in “/usr/lib”, “/usr/local/lib”, etc. Taking the example above, there are extra steps:
The flag “-shared” means compiling a dynamic library. The naming rule of a dynamic library is “lib
Now the file hierachy is
--demo/ \-- test.c \-- my_headers/ \-- blob1.h \-- blob1.c \-- blob1.o \-- my_libs/ \-- libmyblob.a \-- my_dyn_libs/ \-- libmyblob.so
To run the executable in Linux, since the dynamic library “libmyblob.so” is not in the default paths (e.g. /usr/lib; /usr/local/lib), environmental variables need to be updated
Probably it is just easier to place the dynamic library in one of the default paths.
It is very common to have header files and libraries in different folders.
Several GCC flags are reviewed: “-c”, “-I”, “-L”, “l”, “-fPIC”, “-shared”.
The difference between static linking and dynamic linking is demonstrated with an example.