STATIC vs DYNAMIC libraries

Paul Manot
4 min readDec 14, 2020

What are the differences?

What is a library?

So before getting into the differences let’s start with the global definition as both dynamic and static libraries serve the same purpose. A library is a predefined set of functions and variables that can be utilized when writing an application. At its core that’s all a library is. No need to reinvent the wheel each time you write some code. Use the wheel that someone has already built for you! And by the way that’s what you do when you include stdio.h at the top of .c file in order to use printf. There is no need to re-code printf you just use the one from the standard library… Simple! Right?

But there is a little bit more to it…

How do they work?

Whether dynamic or shared, libraries work in a similar fashion. At some stage (more on the specifics later) a piece of code is imported from somewhere else (another file) and is used by the current application. In the case of a dynamic library the code is imported at run time and is actually not even part of the application. On the contrary, with a static library the needed functions and variables are copied along with the rest of the code during compilation making it part of the application and always available.

How do you create a static library?

First you need to package you c files containing your functions into object files (binaries) by running the following gcc command.

$ gcc -c myfile.c

And the result is an object file called myfile.o you can change the name of the destination file as per the following naming convention like so.

$ gcc -c myfile.c -o util_myfile.o

Once you’ve turned all of your functionalities into .o files you can create your static library using a program called ar for archiver. Note that it is also a convention to prepend your filename with the term lib .

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

How to use your static library?

The resulting .a file can then be added to your application.

$ gcc main.o -L . -l util -o prog

Note that we need to use the object version of the main application file not an already fully compiled file and linking -l the library called util in the current directory -L . . Also note that we need to strip util from its prefix lib and extension .a .

To speed up the look up process you can index your library by using another utility called ranlib on your newly created library.

Dynamic Libraries

Unlike static libraries dynamic libraries are not package with the application code and are requested at run time. Therefore they can be shared between different applications.

How to create a dynamic library?

The first step is very similar to a static library but with a key difference. Same as for a static library you need to package your functionality as object files but you give them the -fpic flag to give them a relative address in memory. This is needed because the library will be used by more then one file as it is shared.

$ gcc -fpic -c util_myfile.c

Also note that a shared library is not an archive. Because it is shared it has a different format and can be create with gcc directly using the -shared flag.

gcc -shared libutil.so util_myfile.o util_myotherfile.o

Since the shared library is not an archive it doesn’t have a .a extension but a .so one.

How to use your dynamic library?

The next step is the same as for the static library

gcc main.o -L. -lutil -o prog

but you’ve linked a different type of library which as we’ve mentioned before won’t get added to the code at compilation time. Therefore you need to specify the path to the library in order for it to be used by different applications.

$ LD_LIBRARY_PATH=/full/path/to/library/directory
$ export LD_LIBRARY_PATH

Summary of static vs dynamic libraries which should you use?

Well it all depends on the use case. Static and Dynamic have their pros and cons.

Static

pros:

  • Executables can load faster, because symbol resolution already took place at compile time.
  • No dependencies, all the code needed is packed with the application.

cons:

  • Executables can get really big therefore slow.
  • Executables cannot be updated without relinking.

Dynamic

pros:

  • If an .so is already loaded, the executable may load faster, because it is a smaller file.
  • The code in the library only need to be loaded once (interesting when shared across lots of executables)
  • Executables can be updated without relinking.

cons:

  • All library must be loaded even if a small part of it is required
  • Executables can be broken if the library is being updated.

--

--