Static and Dynamic Libraries

Why are libraries used in computer programming?

A “library” in the context of computer programming, is a file that consists of a function, a collection of functions, variables, classes, or data structures. The general reasons for using libraries are to allow for code sharing and reuse and to provide access to hardware and software components. Using libraries saves disk space, removes redundancy in coding and storage, and allows for isolation and modular control of different components of the code base, for security, efficiency and ease of management.


How do libraries work?

Libraries reside on the disk and are “called” by various applications for use when needed. Creation, compilation and usage of static and dynamic libaries are discussed below.


How are libraries created?

For this explanation, we’ll look at libraries as used in the gnu/Linux operating system.

Creating Static Libraries: (.a)

1) Create the object code:
 
For example, if we want to create a static library containing function_a.c and function_b.c, we can first create the object file myobjectfile.o:

gcc –Wall –Werror –Wextra –pedantic –c function_a.c function_b.c –o myobjectfile.o

2) Create the library:

Then create an “archive” or static library using the ar program:

ar rcs libmylibrary.a myobjectfile.o

Note that library names must start with lib.

Creating Dynamically Linked “Shared Object” Libraries: (.so)

1) Create the object code:
 
For example, if we want to create a dynamically linked “shared object” library containing function_a.c and function_b.c, we can first create the object file myobjectfile.o:

gcc -Wall -Werror -Wextra -pedantic -fPIC -c function_a.c function_b.c -o myobjectfile.o

As contrasted with the creation of a static library, note the use of gcc –fPIC option. This is a gcc directive to output position independent code, a characteristic required by shared libraries.

2) Create the library (and optionally, a default version using a symbolic link)

gcc -shared -Wl,-soname,libmylibrary.so.1 -o libmylibrary.so.1.0 myobjectfile.o

Compilation flags used:

-o 
Output of operation; in this case the name of the shared object to be output will be libmylibrary.so.1.0

-shared
This is a gcc directive to output a “shared” object which can subsequently be linked with other objects to form an executable.

-Wl,-soname,libmylibrary.so.1
This is a gcc directive that establishes the soname, related library version control, and the relationship between lmylibrary.so, libmylibrary.so.1, libmylibrary.so.1.0, and future versions of libmylibrary.so.

You can alternatively cascade the symbolic links:

ln -sf libmylibrary.so.1.0 libmylibrary.so.1
ln -sf libmylibrary.so.1 libmylibrary.so

The link to libmylibrary.so allows the naming convention for the compile flag -lmylibrary to work.
The link to libmylibrary.so.1 allows the run time binding to work. See dependency below.


How to use libraries in Linux

Generally stated, library components are called by various applications for use when needed.

Using the C standard library

The C standard library in gnu/Linux is comprised of individual components which are loaded into the library cache upon startup. To use a particular component of the C standard library, we simply call the appropriate header (.h) file using the include statement, #include <component.h> in our program file and then call any function referenced by that header.

Using Other Static Libraries

From above, consider that we have created a static library as follows:

ar rcs libmylibrary.a myobjectfile.o

We can list the files in the library:

ar -t libmylibrary.a

And compile with our main.c program if the library is in the current directory:

gcc –Wall –Werror — Wextra –pedantic -o executable-name main.c libmylibrary.a

Or alternatively, and if the library resides elsewhere:

gcc –Wall –Werror — Wextra –pedantic –o executable-name main.c –L/path/to/library-directory –libmylibrary

Using Dynamically Linked “Shared Object” Libraries: (.so)

Installation

Dynamic libraries that we create must be installed. We can install libraries using several methods:

a) Placing the library file in a default “trusted” directory:

/lib
/usr/lib
/usr/local/lib
sudo mv libmylibrary.so /usr/lib/

b) Referencing the library in the /etc/ld.so.conf configuration file, or one of it’s dependencies. Typically, these are additional directories put in place by software vendors as they install programs.

We must reload the library cache (/etc/ld.so.cache) with the command: sudo ldconfig to update the library cache after making changes to a default “trusted” directory or the /etc/ld.so.conf file or it’s dependencies.

c) Adding a library and path explicitly to the gcc compiler/linker command using: -lmylibrary -L/path/to/lib

d) Temporarily adding or substituting a library by setting the environment variable LD_LIBRARY_PATH. This variable, normally not set by default, is a colon-separated set of directories where libraries should be searched for first, before the standard set of directories:

export LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH

If the library is in the current directory, as might be the case during development:

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

You can compile a program for run time linking with a dynamically linked library as follows. The libraries will not be included in the executable but will be dynamically linked during run time execution.

gcc –Wall –Werror — Wextra –pedantic -I/path/to/include-files -L/path/to/libraries main.c –lmylibrary -o executablename

or

gcc –Wall –Werror — Wextra –pedantic –L. main.c –lmylibrary –o executablename

Note that the library name we outputted above was libmylibrary.so.1.0 for the library libmylibrary.so but we’ve used lmylibrary in the above compilations. This arrangement is allowed by the establishment of the soname and associated symbolic links (above). This also allows for library version control.

Useful commands

ldd: List dependencies

The shared library dependencies of an executable can be listed with the list dependencies command: ldd name-of-executable:

ldd executablename

nm: The command “nm” lists symbols contained in object files:

nm myobjectfile.o
nm mylibrary.a
nm — dynamic libmylibrary.so.1.0

What are the differences between static and dynamic libraries?

Static libraries (.a) are libraries of object code which are linked with and do become part of the compiled application.

Dynamically linked shared libraries (.so) can be used in two ways:

  • Dynamically linked at run time but statically aware. The libraries must be available during both compilation/linking and program execution. The libraries do not become part of the compiled application.
  • Dynamically loaded and unloaded and linked during execution using dynamic linking loader system functions.

What are the advantages and drawbacks of static and dynamic libraries?

Advantages of statically-linked libraries

Executables using static libraries may load faster and may require less memory because, at compilation, they only require inclusion of those functions from the library that are used by the executable, whereas dynamic libraries require loading the entire library because the functions required are not known in advance.

Executables using static libraries will continue to run if a library is moved, changed, or versioned, whereas executables using a dynamic library may be affected.

Executables using statically-linked libraries are more portable because they include necessary libraries which may otherwise differ across environments, operating systems, and operating system versions. Static linking can also allow the application to be contained in a single executable, which simplifies distribution and installation.

Advantages of shared/dynamically-linked libraries

Dynamic libraries take less disk space and memory. They can be stored in only one place rather than duplicated among compiled executables. Dynamic libraries are also loaded into memory only once; all programs that need to use the library use the same copy.

A dynamic library can be updated or repaired and the change will propagate to all affected executables while a program with statically linked libraries will need to recompiled/relinked.

Dynamic libraries allow for robust version control and package management systems.