Dependency Hell is Coming
Two months ago, I wrote about static libraries in Linux and reasons to use them. In today’s article, I will introduce the concept of dynamic libraries in Linux and aim to cover the following:
- why, in general, C libraries are used
- differences between static and dynamic C libraries
- advantages and drawbacks to each type of library
- how dynamic C libraries work
- how to create and use dynamic C libraries in Linux
Why use C libraries?
Creating a library allows users to group together multiple compiled object code files into one file. This allows a user to share functions with multiple applications. Libraries can be either static or dynamic.
Difference between static and dynamic C libraries
In Linux, static libraries are also known as archive libraries. In my previous post, I drew a comparison between static libraries and encyclopedias. An encyclopedia represents a snapshot of knowledge that at one point in time which cannot be updated without replacing the entire library of books. To further draw out this metaphor, if encyclopedias are static libraries, then wikipedia is a dynamic library, able to be updated at any point and at various levels — sitewide, subject level or page specific.
Advantages and drawbacks to each type of library
- The most significant is that the application can be certain that all its libraries are present and that they are the correct version. This avoids dependency problems, known colloquially as dependency hell.
- Static linking can also allow the application to be contained in a single executable file, simplifying distribution and installation.
- You only need to include those parts of the library that are directly and indirectly referenced by the target executable. With dynamic libraries, the entire library is loaded, as it is not known in advance which functions will be invoked by applications.
- Since applications will be contained in a single file, you ultimately have a larger file size and will need to download the entire file each time you update programs — as you can imagine, this would be quite the hassle to deal with in distributing updates to programs.
- Efficiency — several programs can share the same object code, which saves storage space as well as physical memory during execution.
- When updating programs, instead of downloading the entire application file, only the new dynamic libraries need to be downloaded and the old ones removed.
- DLL Hell — as discussed above, usage of dynamic libraries can lead to dependency hell. In short, this means that programs assuming that a specific dynamic library is available would not work if that library is not installed or incompatible with that version of the program.
- Performance lag — with older machines, there may be a slight lag in speed between static libraries and dynamic libraries.
How dynamic C libraries work
Dynamically linked shared object libraries (.so) can be used in two ways:
- Dynamically linked at run time but statically aware. The libraries must be available during compile/link phase. The shared objects are not included into the executable component but are tied to the execution.
- Dynamically loaded/unloaded and linked during execution (i.e. browser plug-in) using the dynamic linking loader system functions.
How to create and use dynamic C libraries in Linux
There are two steps in creating a dynamic library:
1. Create object code
Once you are in the working directory that you want to create your dynamic library from, run
gcc with the following flags.
gcc -Wall -fPIC -c *.c
-Wallinclude warnings. See man page for warnings specified.
-fPIC: Compiler directive to output position independent code, a characteristic required by shared libraries. Also see “-fpic”.
-cgenerates object code from
2. Create library
Once object code is generated, making your dynamic library is next!
gcc -shared -Wl,-soname,mydynamiclibrary.so -o mydynamiclibrary.so *.o
-shared: Produce a shared object which can then be linked with other objects to form an executable.
-Wl,options: Pass options to linker. In example below the options to be passed on to the linker are:
-soname mydynamiclibrary.so. The name passed with the “-o” option is passed to gcc.
-o: Output of operation. In this case the name of the shared object to be output will be
Once you’ve created your library you can list symbols from object files by running
nm . Use option
-D in order to list dynamic symbols.
From there, you can compile files with your new library. This example is with a different library named
libholberton — notice that in compilation, the library is called as
% gcc -Wall -pedantic -Werror -Wextra -L. 0-main.c -lholberton -o len
To print shared library dependencies, something unique to dynamic libraries, run
ldd on your program.
% ldd len
linux-vdso.so.1 => (0x00007fff5d1d2000)
libholberton.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f74c6bb9000)
If “not found” is returned as it is in line 3 above, then you need to update your environmental variable
% export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
% ldd len
linux-vdso.so.1 => (0x00007fff41ae9000)
libholberton.so => ./libholberton.so (0x00007fd4bf2d9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd4beef6000)