Check out your local (static) library!
You might be familiar with the term library. In the non programming world its a place where you can find and check out books, and in the modern day even access computers or use wifi to access the internet from your own device. Programming languages have a similar system where a library can be used to “check out” code that has been pre written and use it in other programs. Odds are you have used at least one library, possibly without realizing it. In this case I am talking about your #includes such as stdlib.h, stdio.h, math.h, etc. These libraries store segments of code for quick future use, helping to simplify solving future problems, and while most languages have access to standard pre-built libraries such as the examples above, it is possible to create your own libraries filled with your own predefined code. In this article we will look at static libraries, how to make them, and how to use them.
What is a static library?
In technical terms a library is a collection of .o (also known as object) files that are stored into a .a (or an archive) file so that the code they contain may be used in other programs. Beyond this there are two different types of libraries, static and dynamic. The main difference between the two is what happens when compiled. A static library will have its contents built into the executable, removing the need for the library to be present when running the program. On the other hand, a dynamic library will simply create a link between the executable and the library, requiring the library to be present when running the program. The tradeoff is that a dynamic library can be used by multiple programs at once and can be updated without having to recreate the executable.
Why should I use a library?
At this point you might be wondering why you should even bother with a library beyond the standard ones that are provided for you. You have probably already practiced including other .c files into your code and it might seem easier to do so. The simple answer is simplicity and convenience. As the problems you are trying to solve become more and more complex you might need to include more .c files in order to achieve the same task. By using a library you can group all the .c files, and by extension the functions within them, all together so that you can give your program access to all the functions in one go instead of having multiple header and .c files. This reduces clutter in your program, and makes compiling your code a simpler process as well.
How libraries work
If you have any experience with how compilers function, then you probably already know the answer to this question. A library contains all the assembly code from the .o files, and during the linker stage of complication, your complier will take the assembly code from your library and stick it into the executable file that you are creating. This allows you to use the functions of your library inside other code without having to type it all over again. Then when the executable runs it already has everything it needs.
Making a library
There are several steps to making a library.
1. First you must have the .c files that you wish to turn into your library made. This can be done by yourself, or through the help of others.
2. Once you have the collection of .c files you need to make them into .o files using your preferred compiler. Here is an easy way to convert them all at once in gcc
gcc -options_here -c *.c
The -c flag will give us the .o files so that we can combine them into our library, and by using the wild card symbol ‘*’ we are telling our compiler to grab any .c files in the current directory. All the files will be named filename.o replacing filename with the name of the .c file minus the ‘.c’.
3. Now that we have our .o files we can combine them into our library, once again also known as an archive, by using an archiver. We call our archiver using the command ‘ar’. Here is an example call:
ar -rc libname.a *.o
In this example we use the options r and c to create our library. C creates the library itself and r says that if the library exists we will insert new files into the library while replacing any files that share a name with the newer files that we are currently adding. So say you had liba and you wanted to add to it the functions add, mul, and compare. If mul already existed in liba, it would be deleted first then the version of mul that you just ran with the ar command would be added in its place. We save our library as a .a file to signify that it is an archive file. Once more the wildcard ‘*’ lets us grab all the object files at once so that we are not running the command for each individual file.
3a. This step is techincally optional but it is always a good idea to run it so that you know your library was archived properly.
ar -t libname.a
This creates a table with the contents of you archive file so you can confirm it has everything you wanted to add.
4. Finally now that we have our .a file we need to index it. By indexing our archive it stores the symbols of each .o file so that libraries can make calls to each other without running errors and speeds up compilations. This is achieved with the ranlib command which will add an index to our archive, and the same result could be achieved using ar -s. So our command would look like:
ranlib libname.aorar -s libname.a
How do I use a library?
Now that you have your library made you need to know how to use them. The first step is to include the library in the file that you are writing. Standard practice is to include the library info in a separate header file then include that header file in your main file. In this case it would be:
You use .h to indicate a header file, and the .a file will be run in the compiler through a special tag that I will show you now
gcc mainfilename.c -L -l'libname'
In the example above you would replace ‘libname’ with your actual library name, so if your library was games.a, you would run -lgames . Notice that we do not use .a in this case, that is because the -L tag is looking for a link to a library, and the -l’libnam’ is where our library link is stored. The complier will run and add your library code to your mainfile code. Since we have been creating and using a static library the executable can be run even if moved, but if you ever need to update the code in your library you will have to repeated the steps to update your .a file and recompile so that the executable will be made with the updated code. And that is all there is to making and using static libraries.