What are libraries in programming?

Estefano Misme
5 min readSep 25, 2021
source: https://linpei.blogspot.com/2014/09/static-linking-vs-dynamic-linking.html

Libraries are files containing various compiled functions that will be used in the execution of a program.
Its usefulness lies in saving time and space when using various programs. If we have functions that we want to reuse in another program, we can compile it by linking it only with the library we have, instead of the source files that were used to create the library, and the new executable will be able to use the functions without problems.

There are two types of libraries: static and dynamic. Both differ in the way of linking with the program that will use it. Static libraries are linked to the program when compiled, and then all the functions that it needs are inserted into the executable. Whereas dynamic libraries are linked to the program at the time of its execution. Instead of inserting the functions into the executable, the program will call the library when one needs to be executed.
These differences mean that the presence of the library is necessary if the program has been compiled dynamically, which is not the case with the static library, which can be modified or deleted without affecting the program.

Each type of library has its advantages and disadvantages when it comes to use. For example, static libraries make the executable file heavier, but they make up for it by faster execution. And since it does not need the presence of the libraries once compiled, the program can be transferred to another computer without them. Dynamic libraries can modify the behavior of the executable, and this is useful if we already have the executable linked to the library and need to change some function due to errors. Then it will not be necessary to recompile the program, only the library.

There are several ways to create libraries. Next, we will explain one of them.

  • First, we need the source code of the functions, as well as their .h header file. We will give an example of this.
vagrant@ubuntu-focal:~/sample/new/libtest$ ls
function1.c function2.c function3.c main.c main.h
vagrant@ubuntu-focal:~/sample/new/libtest$ cat main.h
#ifndef MAIN_H
#define MAIN_H
#include <stdio.h>void function1();
int function2(int a);
char function3(int ascii);
#endif
vagrant@ubuntu-focal:~/sample/new/libtest$ cat function1.c
#include "main.h"
void function1()
{
printf("This is a function.\n");
}
vagrant@ubuntu-focal:~/sample/new/libtest$ cat function2.c
#include "main.h"
int function2(int a)
{
printf("%d", ++a);
return a;
}
vagrant@ubuntu-focal:~/sample/new/libtest$ cat function3.c
#include "main.h"
char function3(int ascii)
{
printf("%c", ascii);
return ascii;
}
vagrant@ubuntu-focal:~/sample/new/libtest$ cat main.c
#include <stdio.h>
#include "main.h"
int main()
{
function1();
function2(4);
putchar('\n');
function3(64);
putchar('\n');
return (0);
}

The functions stored within the function1.c, function2.c and function3.c files are referenced in the main.h header file, which is included within the main.c program.

  • What we need now is to compile the files that store the functions defined in the header file, and obtain their object files with the extension .o. To do this, we execute the gcc command with the -c flag, followed by all the files we need.
vagrant@ubuntu-focal:~/sample/new/lib$ ls
function1.c function2.c function3.c main.c main.h
vagrant@ubuntu-focal:~/sample/new/lib$ gcc -c function*.c
vagrant@ubuntu-focal:~/sample/new/lib$ ls
function1.c function1.o function2.c function2.o function3.c function3.o main.c main.h

Now, if we want to create static libraries, we will do the following:

  • We execute with the ar program (a creator, editor and file extractor) and its flags r (which allows inserting different files in our destination, or replacing old objects with new ones if they have the same name) and c (to create the file). Preferably, the name that we add to this new file should have the prefix lib- to remember that it is a library.
  • Static libraries have the extension .a. The result is as follows:
vagrant@ubuntu-focal:~/sample/new/lib$ ls
function1.c function1.o function2.c function2.o function3.c function3.o main.c main.h
vagrant@ubuntu-focal:~/sample/new/lib$ ar rc libfunc.a function*.o
vagrant@ubuntu-focal:~/sample/new/lib$ ls
function1.c function1.o function2.c function2.o function3.c function3.o libfunc.a main.c main.h
  • If we want the program to run faster, we will need to index the created library, which will speed up the search for the necessary functions. To do this, we will use the ranlib command.
  • The library will save the names of the object files from which it was created. We can see them using the t flag of the ar program. If we want more detailed information (for example, about symbols and indexed objects), we can review it with the nm command.
vagrant@ubuntu-focal:~/sample/new/lib$ ls
function1.c function1.o function2.c function2.o function3.c function3.o libfunc.a main.c main.h
vagrant@ubuntu-focal:~/sample/new/lib$ ranlib libfunc.a
vagrant@ubuntu-focal:~/sample/new/lib$ ar -t libfunc.a
function1.o
function2.o
function3.o
vagrant@ubuntu-focal:~/sample/new/lib$ nm libfunc.a
function1.o:
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T function1
U puts
function2.o:
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T function2
U printf
function3.o:
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T function3
U putchar
  • In order to use the static library in the main.c file we have, we need to link both files when compiling. We can do it in the following way:
    gcc <main file> -o <executable> <library>. You don’t need to have your .c source files or .o object files.
  • The result of the execution of the program compiled with the static library that we have created will be shown below.
vagrant@ubuntu-focal:~/sample/new/lib$ ls
function1.o function2.o function3.o libfunc.a main.c main.h mov
vagrant@ubuntu-focal:~/sample/new/lib$ mv function*.o mov/
vagrant@ubuntu-focal:~/sample/new/lib$ ls
libfunc.a main.c main.h mov
vagrant@ubuntu-focal:~/sample/new/lib$ gcc main.c -o staticex libfunc.a
vagrant@ubuntu-focal:~/sample/new/lib$ ls
libfunc.a main.c main.h mov staticex
vagrant@ubuntu-focal:~/sample/new/lib$ ./staticex
This is a function.
5
@

To create dynamic libraries, we will use the ld program, this program will link all the given files and with the -shared option, it will create a dynamic library with them. In the same way as with static libraries, we will need the object .o files of the compiled functions.

  • The dynamic library must have the extension .so if we work on Linux.
vagrant@ubuntu-focal:~/sample/new/lib$ ls
function1.o function2.o function3.o main.c main.h mov
vagrant@ubuntu-focal:~/sample/new/lib$ ld -o libdynfunc.so function*.o -shared
vagrant@ubuntu-focal:~/sample/new/lib$ ls
function1.o function2.o function3.o libdynfunc.so main.c main.h mov
  • As with static libraries, you can review the contents (functions and symbols) of the library with the nm command.
vagrant@ubuntu-focal:~/sample/new/lib$ ls
libdynfunc.so main.c main.h mov
vagrant@ubuntu-focal:~/sample/new/lib$ nm libdynfunc.so
0000000000003f00 d _DYNAMIC
0000000000004000 d _GLOBAL_OFFSET_TABLE_
0000000000001070 T function1
0000000000001087 T function2
00000000000010b5 T function3
U printf
U putchar
U puts
  • In order to use the dynamic library with a file, you have to compile it by linking it to the main file. For this, the gcc command and its Bdynamic flag will be used.
vagrant@ubuntu-focal:~/sample/new/lib$ ls
libdynfunc.so main.c main.h mov
vagrant@ubuntu-focal:~/sample/new/lib$ gcc -o dynexm main.c -Bdynamic libdynfunc.so
vagrant@ubuntu-focal:~/sample/new/lib$ ls
dynexm libdynfunc.so main.c main.h mov
vagrant@ubuntu-focal:~/sample/new/lib$ ./dynexm
This is a function.
5
@
  • Unlike what happens with static libraries, dynamic libraries have to be present in the directory where the executable it was linked to is in order for it to be used. Otherwise, an error will occur.
#example with dynamic libraries
vagrant@ubuntu-focal:~/sample/new/lib$ ls
dynexm libdynfunc.so main.c main.h mov
vagrant@ubuntu-focal:~/sample/new/lib$ mv libdynfunc.so mov/
vagrant@ubuntu-focal:~/sample/new/lib$ ls
dynexm main.c main.h mov
vagrant@ubuntu-focal:~/sample/new/lib$ ./dynexm
./dynexm: error while loading shared libraries: libdynfunc.so: cannot open shared object file: No such file or directory
#example with static library
vagrant@ubuntu-focal:~/sample/new/lib/mov$ ls
function1.c function1.o function2.c function2.o function3.c function3.o libdynfunc.so libfunc.a staticex
vagrant@ubuntu-focal:~/sample/new/lib/mov$ mv libfunc.a ..
vagrant@ubuntu-focal:~/sample/new/lib/mov$ l
function1.c function1.o function2.c function2.o function3.c function3.o libdynfunc.so* staticex*
vagrant@ubuntu-focal:~/sample/new/lib/mov$ ./staticex
This is a function.
5
@

--

--