What is a static library in C?

Miguel Enrique Grillo Orellana
6 min readOct 26, 2021

In this article we will talk about what a static library is, what it is for, why and in which cases it is good to use it. Also, we will see how to compile files into objects and even compile the entire directory at once to save time. In addition and above all, how to create a static library and how to use and make use of this wonderful tool, which provides us with a file with multiple functions inside.

In the C programming language, a static library also called object and header libraries that is, files with the extension “.o” and “.h” respectively. So it is a file or collections of object files and headers that are compiled. Normally, the library is indexed, that is, it is linked and has an extension, so the symbols are easy to find. For example, functions and variables. In addition, they are grouped into a single file with the extension .lib, .a, etc.

What is it for? Why use a static library?

It helps us link a program whose object files are organized in libraries, which is faster than linking a program whose files are separated on disk. Also, the reason why we use it is because by using a library we have fewer files to search and open and as a consequence it speeds up linking even more.

We have a problem in which we have several functions and what we want to do is use each necessary file one by one, but thanks to the static library we can group all the functions together, and thus only compile the file where we will use the functions plus the static library “.a”.

So we will proceed to create one. We will do the step by step of how to make a static library.

How to create them:

1. Create a header where we will place the prototypes as in the following image, then enter the initial macro #ifndef <HEADER>_H and #define <HEADER>_H at the top and when you finish entering the prototypes add #endif at the bottom so that the header file is only defined once instead of each call.

#ifndef MAIN_H
#define MAIN_H
0-isupper.o
0-memset.o
0-strcat.o
1-isdigit.o
1-memcpy.o
1-strncat.o
100-atoi.o
2-strchr.o
2-strlen.o
2-strncpy.o
3-islower.o
3-puts.o
3-strcmp.o
3-strspn.o
4-isalpha.o
4-strpbrk.o
5-strstr.o
6-abs.o
9-strcpy.o
_putchar.o
#endif

2. Compile the “.c” files and use the -c option to compile and create an object file without a linker or assembler and only with a preprocessor and compiler, resulting in the extension “.o”. Also, to compile with gcc with all the “.c files in the current directory we can use the following code

gcc -c *.c

3. Now that we have all the required “.o” files, we will proceed to execute the following command in the static library (.a) that we want and in this example we will use libmy.a

ar -rc libmy.a *.o

Here we use the command “ar” which comes from the word “archiver”. This program can be used to create static libraries which are actually archive files. Also, we can modify object files, enumerate the names of the object files, etc.
With this command, we are using the “
-rc” options where “r” is to verify that if the static library file (.a) exists then it will be replaced. The “c” tells “ar” to create the library if it doesn’t already exist.

4. To finish we will index the content of a file and store it in the file with the ranlib command with the static library.

ranlib libmy.a

ranlib generates an index of the contents of a file and stores it in the file. The index lists each symbol defined by a member of a file that is a relocatable object file. So ranlib is used to create and modify libraries. It is up to the linker to use them, usually passing the location and/or the name of the library on the command line.

Now we have a static library

So now we are going to see how we can use it and how it works for us.

Remember that if we make any changes to a “.c” file and we want it to impact our static library, we will have to perform the previous steps taught in “How to create them”:

How to uses:

1. Move the library file (.a) to the same directory where the file you want to compile resides, for example /root/holberton_low_level directory.

mv libmy.a /root/holberton_low_level

2. Create a file with name main.c and with what we want to use inside. For example, we want to validate if the data they give us is digits.

Ineffable22@ubuntu:~/0x04$ cat main.c int _isdigit(int c);

/**
* main - check the code
*
* Return: Always 0.
*/
int main(void)
{
char c;

c = '0';
printf("%c: %d\n", c, _isdigit(c));
c = 'a';
printf("%c: %d\n", c, _isdigit(c));
return (0);
}

3. Now instead of having to include all the relevant file names in the build command, you just need to reference the static library (.a).

gcc main.c libmy.a

4 We only have to execute “./a.out” and will result in the following

0: 1
a: 0

Additional details that can be done with the library

  • Lists prototypes
Ineffable22@ubuntu:~/#$ ar -t libmy.a 
0-isupper.o
0-memset.o
0-strcat.o
1-isdigit.o
1-memcpy.o
1-strncat.o
100-atoi.o
2-strchr.o
2-strlen.o
2-strncpy.o
3-islower.o
3-puts.o
3-strcmp.o
3-strspn.o
4-isalpha.o
4-strpbrk.o
5-strstr.o
6-abs.o
9-strcpy.o
_putchar.o
  • Lists prototypes and displays the table of symbols associated with an object, object file library, or executable files.
Ineffable22@ubuntu:~/#$ nm libmy.a 

0-isupper.o:
0000000000000000 T _isupper

0-memset.o:
0000000000000000 T _memset

0-strcat.o:
0000000000000000 T _strcat

1-isdigit.o:
0000000000000000 T _isdigit

1-memcpy.o:
0000000000000000 T _memcpy

1-strncat.o:
0000000000000000 T _strncat

100-atoi.o:
0000000000000000 T _atoi

2-strchr.o:
0000000000000000 T _strchr

2-strlen.o:
0000000000000000 T _strlen

2-strncpy.o:
0000000000000000 T _strncpy

3-islower.o:
0000000000000000 T _islower

3-puts.o:
U _putchar
0000000000000000 T _puts

3-strcmp.o:
0000000000000000 T _strcmp

3-strspn.o:
0000000000000000 T _strspn

4-isalpha.o:
0000000000000000 T _isalpha

4-strpbrk.o:
0000000000000000 T _strpbrk

5-strstr.o:
0000000000000000 T _strstr

6-abs.o:
0000000000000000 T _abs

9-strcpy.o:
0000000000000000 T _strcpy

_putchar.o:
0000000000000000 T _putchar
U write

A detail in the latter in nm. Your toolchain will likely generate position independent executables (PIE) by default such as “U_GLOBAL_OFFSET_TABLE_”. In that case try compiling with gcc -fno-pie and that will fix it.

On the other hand, with gcc you can mix options and other arguments. For the most part, the order you use doesn’t matter. Order matters when you use multiple options of the same type; for example, if you specify -L more than once, the directories are searched in the specified order. Also, the location of the -l option is significant.
The directories searched include several standard system directories plus any that you specify with
-L.

gcc -l / gcc -L

Typically, the files found in this way are library files, archive files whose members are object files. The linker handles an archive file by scanning it for members that define symbols that have hitherto been referenced but not defined. But if the found file is an ordinary object file, it is linked in the usual way. The only difference between using an “-l” option and specifying a filename is that “-l” surrounds the library with lib and “.a” and searches multiple directories.

In conclusion, we were able to observe in detail how a static library is created, what it is for and why it is so important to use it. Also, remember that technology is to optimize and streamline processes and that is exactly what the static library does, simplifying the compilation process, making little use of resources and above all taking up less space on disk.

--

--