Static Libraries in C
Ana Maria Roman
DevOps Engineer | Cloud Engineer | AWS | Women Who Code Medellín | DevOps Medellín ??????
Simply put, a library is a collection of items that you can call from your program. It obviously has a lot of advantages, not least of which is that you can save much time by reusing work someone else has already done and be more confident that it has fewer bugs (since probably many other people use the libraries too, and you benefit from having them finding and fixing bugs). A library is exactly like an executable, except instead of running directly, the library functions are invoked with parameters from your executable.
What is a Static library?
The most straight forward way of using a library function is to have the object files from the library linked directly into your final executable, just as with those you have compiled yourself. When linked like this the library is called a static library, because the library will remain unchanged unless the program is recompiled. This is the most straight forward way of using a library as the final result is a simple executable with no dependencies.
There is other type of library called Dynamic Library( or Shared Library) ,but more on that later, for now we will discuss about Static Library in detail.
Static libraries are object files that are later combined with another object to form a final executable.
By convention they have the prefix lib and the suffix .a — for example, libholberton.a
Creating a Static Library file
To create a static library using GCC we need to compile our library code into an object file so we tell GCC to do this using -c
$ gcc -c *.c
Here in the above command , all the .c extension files( C files) in the current working directory have been converted in to their respective object files. Once we have object file(s), we use the GNU ar command to create our final library/archive
The archiver, also known simply as ar, is a Unix utility that maintains groups of files as a single archive file.
$ ar -rc libholberton.a *.o
This tells ar to create an archive (option c) and to insert the objects, replacing older files where needed (option r) .
Whenever files are added to a library, including the initial creation of the library , the library needs to be indexed, which is done with the command ranlib. ranlib makes a header in the library with the symbols of the object file contents.This helps the compiler to quickly reference symbols. A large library may have thousands of symbols meaning an index can significantly speed up finding references.
$ ranlib libholberton.a
This step may or may not be necessary depending on your computer system or your archiver(not necessary with ar).
If we want to see the contents of our library, we can use the ar option -t.
ar -t libholberton.a
We can also see the symbols in our library, using the command nm, which lists each symbol’s symbol value, symbol type, and symbol name from object files.
nm lib_test.a
We have now created a static library libholberton.a and now let us use the static library by invoking it as part of the compilation and linking process when creating a program executable. Incase of gcc we use following flags to create static library
- -l<libraryname without lib prefix and extension>
- -L : specifies the path to the library .We can use -L. inorder to point to the current directory and -L/home/tmp to point to the /home/tmp directory.
gcc main.c -L. -lholberton -o main
Now run the executable program ‘main’
$./main
Executables generated using static libraries are no different than executables generated from individual source or object files. Static libraries are not required at runtime, so you do not need to include them when you distribute your executable. At compile time, linking to a static library is generally faster than linking to individual source files.
Static linking is very straight forward, but has a number of drawbacks.
The two main disadvantages are.
- If the library code is updated (say, to fix a bug) you have to recompile your program into a new executable.
- Every program in the system that uses that library contains a copy in its executable. This is very inefficient (and a pain if you find a bug and have to recompile, as per point one).
It is in these cases that we find Dynamic or Shared libraries better. Shared libraries are an elegant way around the problems posed by a static library. A shared library is a library that is loaded dynamically at runtime for each application that requires it. But more on this in another post.
I hope you liked and served this article !