Black & White & Read All Over
A comprehensive expansion on Static and Dynamic Libraries
In the world of coding, libraries are vital. Initially built-in libraries can seem like the only thing one could need, but as functions are built and projects are worked on, a self made library could prove more effective. To truly make the most of the capabilities surrounding coding, one can implement static or dynamic libraries. In my previous article, I addressed the initial differences in the two libraries. In this article, I aim to broaden the understanding on what these applications actually look like. To read this initial exploration, please follow the article linked below.
Using Static & Dynamic Libraries
A deep-dive into what they are, how they work & how to make and use them.
To overview the previous article, we’ll start with the static library. The statically-linked library has a much narrower scope than a dynamic library, and with that in mind, has limited capability. When a static library is used, the library can only be used within that file hierarchy, interacting only with specific files. If this library was called outside of its scope, the library would not be able to be used. One way to ensure it could be used is by making the library dynamic. This is created by using the flag -fPIC, or Position Independent Code, which creates a symbol table to reference usage of the library across the system. Using this will declare the library independent, and to finalize its capabilities, the library must be brought to the PATH. This ensures that no matter the absolute address of the library, it can be utilized in a myriad of ways, allowing more streamlined memory usage. As seen below, using one extra flag can change the entire structure of a project.
Now that we’ve looked at the differences, let’s focus on the similarities. In both lines of code there is the base command gcc, the foundation for compiling files in the C language. The GNU Compiler Collection has a large collection of flags and ways to manipulate the format, most starting with -f or -W. Of those sorts of flags, most have positive and negative forms, so although it can seem a little daunting at first, the gcc manual page can be extremely useful for compilation manipulation.
Getting into gcc
Although it may seem tiny, running gcc main.c has a broad impact. Before we dive into the details, it’s important to…
In a previous article linked above, we dove into the basics of the GNU Compiler Collection and the intricacies between the Preprocessor, Compiler, Assembler and Linker. Today we will focus our attention on the flag -c. In the below snippet from the gcc manual page, we see a dry bit of language that says nothing about libraries. But if you were to think of the order that the gcc command runs in, it’s right before you.
With the -c flag, almost every stage is completed, except the linking phase. This creates an output of an object file, meaning the ending suffix is replaced with .o and anything not needing compilation or assembly are left alone. This creates a file full of real compilation output, peppered with low level instructions known to the CPU.
Once the object file is created, the above command is used to convert it into a library. This is done first with the wildcard. The *.o ensures all files with .o are compiled. Next the -shared command, as seen below, is used to establish that indeed this is a dynamic library. The GNU Compiler Collection even has the -static option to ensure that linking with shared libraries does not happen.
Next we have the -o flag, which helps specify the file name. In this case the filename being established is liball.so. The beginning lib and the ending .so are vital for enabling a library to be used. Depending on your project or amount of libraries you’ve created, you might want to create a more distinct name than our example by swapping out the word all with any desired name. Once this is done, the dynamic library may be moved to the PATH with the below command. This will ensure that the library can be called from any location in the system, traversing along the symbol table to seamlessly work.
Although they are both from a similar vein of idea, both static and dynamic libraries are built on very different computing structures. For instance, with a static library, the referenced functions in the input objects are automatically copied into the final executable. To use the newly built library, the -l specifier is used before the library’s name, so in our above example we’d say -lall to use the library with a file. With dynamic libraries, a symbol table is established to enable a flexible, dynamic linking within the library’s functions. This symbol table within the PATH is exactly why dynamic libraries can work across various project scopes and static libraries have to stay within their scope. This also lends its hand into thinking about memory efficiency. If a library has the potential to be used more than once, it might be useful to make it dynamic. If it will only be used once, save the capabilities of a dynamic library and just keep the library static and local.
With all the little things happening under the hood, it can seem purposeless or overwhelming to create a library, but once everything is all set up, static and dynamic libraries can be a huge time and memory saver. Whether you’re just starting coding, or have had your hand in it for a while, creating libraries can be a huge game changer for your code.
— — Written by Kathleen R McKiernan for Holberton School NHV — —