C Static Libraries — What and Why?

So let’s say you’re creating a very large project, with lots of different functions and files. You’d probably want to use some of the functions you created in other files. It wouldn’t be very efficient to rewrite every function in every file — that would take up time and lots of unnecessary memory space. There should be a way to somehow link all of these function files together, so that we could use them anywhere we wanted to. That’s where static libraries come in!

So what are static libraries? A library is a file containing several object files, that can be used as a single entity in a linking phase of a program. In simple words, a library holds a bunch of different object files (compiled C files). We can use this library in any other file, and in the linking step of compilation the program will know to access the library.

C files in the directory

How do we create a library? In the picture you can see we have lots of different C files, and also a header file (holberton.h), which contains all the different function prototypes.

The first thing we need to do is create object files, in order to link them together in the library. We’ll use the gcc command (what is the gcc command?) to compile our files.

gcc -Wall -pedantic -Werror -Wextra -c *.c

The asterisk wildcard (what is a wildcard?) compiles all the .c files at once, instead of writing out the command separately for each file. After running this command, we will now have files with a .o (object files) extension as well as the original files.

Now that we have all of our object files, it’s time to create a library to join them all together. We will use the command ar. What does this command do? Let’s look into the man page of this command — “The GNU ar program creates, modifies, and extracts from archives. An archive is a single file holding a collection of other files in a structure that makes it possible to retrieve the original individual files”. The structure of this command looks like — ar [OPTIONS] archive_name member_files.

We have to give the library a name, and include the files we would like to link to it. Instead of adding each object file to the library separately, we could use the asterisk wildcard again!

ar -rc libmylibrary.a *.o — the flags ‘r’ and ‘c’ are both necessary. The ‘r’ flag tells the program to add new files if they don’t exist already, and to update them if they do. It’s recommended to use this flag whenever using the ar command. The ‘c’ flags purpose is to let the program know we are creating a library for the first time. After creating the library, it’s suggested to index it using the command ranlib libmylibrary.a. This generates an index to the contents of the library, and stores it inside. Using this speeds up the linking phase of the compilation.

Congrats! We finally have our usable library. We can take a look at its contents using the nm command as such — nm libmylibrary.a. This will display the symbol table of each object file in the library. This is also possible to do with the ar -t flag.

I think it’s time to create amain.c file and see how we connect it to out library.

We’ll create a very basic C file with just one main function.

int main(void)
{
print_alphabet();
return 0;
}

Without using a library, we would get a compile error that the function print_alphabet does not exist. To attach the library to our main file, we’ll use the gcc with special flags.

  • -l <libraryname without lib prefix and extension>
  • -L with the path, or in our case the . character to specify that the library is in the current working directory.

Our final command would look like gcc main.c -L. -lmylibrary -o main.

After running the compiled file we just created with — ./main, we would get the output abcdefghijklmnopqrstuv. It worked!

Software Engineer in Tel Aviv. Reach out- me@eitanmayer.com :)