Dynamic and Static Libraries in Linux

Static Libraries

Using a shared library is done in two steps:

  1. Compile Time — The linker scan the shared library while building the executable program, so it will be convinced that no symbols are missing. It will not really take the object files from the shared library and insert them into the program.
  2. Run Time — The system’s dynamic loader (the process in charge of automatically loading and linking shared libraries into the running process) where to find our shared library.

How to create them

  1. A static library is basically a set of object files that were copied into a single file.

gcc -Wall -Werror -Wextra -pedantic -c *.c

The -c flags sats not to run the link, then the output consists of object files output by the assembler.

2. Archive the object files

ar rc libutil.a util_file.o util_net.o util_math.o

'ar' stands for 'archiver'. This program can be used to create static libraries (which are actually archive files), 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, we can use a command like this:

The 'c' flag tells ar to create the library if it doesn't exist. The 'r' flag replace older object files in the library, with the new object files.

How to use them

gcc main.0 -L -lutil -o prog

The linker will look for the file libutil.so and link it to the program using the -L. flag.

Dynamic Libraries

Example Files

foo.c

#include <stdio.h>
void foo(void)
{
printf("Shared Library\n");
}

foo.h

#ifndef foo_h__
#define foo_h__
extern void foo(void);
#endif  // foo_h__

main.c

#include <stdio.h>
#include "foo.h"
int main(void)
{
printf("This is a test\n");
foo();
return 0;
}

How to create them

  1. Create Object

gcc -fPIC -Wall -Werror -Wextra -pedantic -c foo.c

The -c flags generate object files.

Use -fPIC -fPIC or -fpic to generate code.

Note: the -fPIC flag always work, but product larger code than -fpic. While -fpic product smaller code, it may have platform-dependent limitations.

2. Create the library

gcc -shared -o libfoo.so foo.o

The creates a libfoo.so libraries from the object file

Note that the -shared flag creates a shared object which can then be linked with other objects to form an executable.

How to use

The linker does not know where the shared library is located, so in order to tell the linker where to find the library, you need to do so with the -Lflag

$ gcc -L/home/username/librarydirectory -Wall -o test main.c -lfoo
$ ./test
This is a test
Shared Library

if you do not use the -Lflag, you will most likely get the error:

error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory

Alternatively, you can set up the LD_LIBRARY_PATH

export LD_LIBRARY_PATH=home/username/librarydirectory

Now, you can just run ./test

$ ./test
This is a test
Shared Library

The Disadvantages of Static Libraries

The issue with static linking: (1) all the functions will be included as a executable, so size will increase. (2) programs that uses the libraries will have to recompile to order to include updates.

The Advantages of Shared Libraries

Dynamic/shared libraries saves space. If libraries could not be loaded dynamically, the code would be linked into every program that needed it, duplicating that piece of code all over your system. This would consume disk space and make updates much more difficult. By using shared libraries, the a function can be stored in one library that is available to any program that needs to use it. In addition, only one copy of the library needs to be updated if a bug needs to be fixed. Shared libraries address the weaknesses of static libraries.