STATIC LIBRARIES AND THEIR GREAT POWER OF REUSE

Luis Fernando Manrique Chavez
7 min readFeb 28, 2022

--

When we talk about libraries, in fact we think of a set of stacked books full of valuable information in which concepts and theories of the most brilliant minds in history have been captured.

Okay, I’m exaggerating a bit, but static libraries are a somewhat similar concept, only we do it with code, come with me to see what all this library stuff is about.

Why use libraries?

Libraries in a nutshell are a collection of object files or elements which we can call from our program, and which can be used as a single entity in a link phase of a program.

The really powerful thing about using libraries is that with them, we can call various functions that we have stored within them, in order to make our code reusable.

We must use static libraries when we have many separate files that will be called within my program and that by the very fact of being separated into several files will make the compilation process take longer than having everything in a single package (library) from where the compiler will search directly.

Also, doing the process of linking a program whose object files are arranged in libraries makes it faster than linking a program with separate object files on disk.

reusable
With the libraries we manage to have reusable code. Source: Own

How they work?

As we know in the last article on compilation, I explained what is the path that a program follows in order to be compiled and transformed into an executable file that the computer can understand.

On that occasion, we saw that the last part of the compilation process is Linking, in which a file is received in object format that contains the machine code.

GCC compiler with static Library — Source: Own

In this last stage, our compiler takes the object code generated in the assembly stage and combines it with the libraries that are present.

It is there that the static libraries adhere to the code in the last step of the compilation of our file. In this way, we can compile our file by adding the static library that we have generated to reuse the functions that we have already created previously.

So, if we have, for example, 5 or 6 functions that we use in a program, it would not be necessary to place all the files of each function at the time of compiling, but it would be enough to just add the static library as a parameter at the time of compilation, since this library contains all the functions that we will use in our program.

We can create static libraries with a program called “ar”, per archiver. With this program you can do many things from creating static libraries, listing the names of the object files in the library, modifying object files in the static library, among other things.

List of functions in c. Source: Own

Before using the “ar” program, we must convert our functions into object files and, as we saw in a previous post, we can do it with the following command:

gcc -c *.c

With this command we tell our compiler to do the compilation and to stop after doing the assembler, and as a result we have the object file or machine code.

List of functions in object format. Source: Own

Now we can use the ar program to generate our static library. It is worth mentioning that ar (archiver) is a utility that Unix has by which it maintains groups of files as a single file.

ar rc libmy.a *.o

In this command, we can see that there are certain options that we will explain below:

  • ar is for you to create a file and insert the objects
  • The r option means replace older files where necessary.
  • The c option means that if the library that creates it does not exist.
We can see libmy.a library created. Source: Own

It is important to mention that after creating the library, it is necessary to index it. The compiler looks for this index to speed up the search for symbols within the library, and in order to make sure that the order of the symbols doesn’t matter during compilation, we can use the “ranlib” command, as shown below.

ranlib libmy.a

As you may have already noticed, the name of the libraries have a prefix and a suffix that are always repeated, these are lib and .a respectively. So the name of the library as such in this case would be “my” and we will see later how we can use this name to call our library more directly.

In order to view the content of our library that we have created, we can use the “ar” command, as shown below.

ar -t libmy.a
The content of our library. Source: Own

We can also see the symbols of our library, using the following command:

nm libmy.a
Symbols of our library. Source: Own

How to use them?

In order to use our static library, it is as we have already explained above to call the library as a parameter when we are using the gcc compiler with the following flags.

First, as an example, what we will do is create an example main.c file which will use a puts function that we have inside our static library, we will demonstrate how it would be to compile without the library and with the library.

First an example without the library

We have the file main.c

Content of file main.c. Source: Own

And the puts function shown below

Function puts. Source: Own

Normally to compile this file we must add the 3-puts.c file and the main.c file.

gcc -Wall -pedantic -Werror -Wextra -std=gnu89 _putchar.c main.c 3-puts.c -o 3-puts

And after compiling our code and running it gives us the following result

Output after compilation with function. Source: Own

In this case we are talking about only one function but let’s imagine that we use 10 functions in a specific program then we should add all the functions as the 3-puts.c function was added, and that would delay the compilation process more and more while more functions are within a program.

For this reason, thanks to having a static library and having done the ranlib process, we can make our compilation much faster since now everything will be packed in one place, which will be our library.

In order to compile and use our library, what we will do is the following:

gcc -Wall -pedantic -Werror -Wextra -std=gnu89 -o 3-puts main.c -L. libmy.a
Output after compilation with library. Source: Own

It should be mentioned that gcc’s -L flag tells the linker that the libraries can be found in the given directory (‘.’, referring to the current directory), in addition to the standard locations where the compiler looks for system librarie.

Also as we said we can call our library by placing “-l” in front of the name of my library and there would no longer be the need to place the “.a” extesion, as shown below.

gcc -Wall -pedantic -Werror -Wextra -std=gnu89 -o 3-puts main.c -L. -lmy

As we can see, the way we compile our code is much faster, as well as being able to reuse code in a much simpler way.

Advantages and disadvantages of using static libraries

  • One of the big disadvantages that static libraries have is that in the event that the code of a function is updated due to improvements in the algorithm or because there is an error and we want to fix it, then we must regenerate the library again and as you can imagine we have to recompile our code.
  • Also another disadvantage occurs when you have a large number of object files inside a library, every program on the system that uses that static library contains a copy in its executable file and that makes it very inefficient.

To solve these problems is that there are dynamic libraries whose main characteristic is to be a shared library and that is loaded dynamically at runtime when the application needs it.

So far I hope I have contributed to learning a little more about static libraries and their powerful functionality within code reuse.

--

--