C Breakdown: Static vs Dynamic Libraries
Libraries are collections of object files containing functions and other useful code that are collected into one file and meant to be used to develop other programs. A static library is a library that is linked via static linking to the program during compilation whereas dynamic (or shared) libraries use dynamic linking. This blog seeks to demystify the differences, advantages, and disadvantages of both static and dynamic libraries.
What are the differences?
As mentioned previously, static libraries use static linking and dynamic libraries use dynamic linking, but what does this mean? Linking is when you take a group of object files and connect them together into one executable. The difference between static and dynamic is when the linking happens. Static linking happens upon compilation, which means the program is 100% ready to run right away after compiling. Dynamic linking happens when the program runs, which means you have to have the library available to run the program.
What are the advantages of each?
Most of the advantages are pretty clear and easy to understand right of the bat. The main advantage of static libraries is that the linking only needs to happen once and the program can then be used anywhere and on any machine that is able to run it. This makes distribution and troubleshooting a lot easier. On the other hand, dynamic libraries have the advantage of being very easy to update or change and all the changes will be applied to every program that uses said library. Another advantage of dynamic libraries is that multiple programs can use the same copy of it, saving space in certain cases.
How about the disadvantages?
Almost any advantage that one type has, the other has as a disadvantage for. With static libraries, the programs that use them need to be recompiled every time there is an update to the library that the program requires. Programs that use static libraries are also usually larger than an equivalent program that uses a dynamic library as the library is not part of the compiled file when linked dynamically. For dynamic libraries, the main disadvantage is that in order for the program to run, the machine also has to have the library installed. This means that the user has to install two things rather than just one. Dynamic linking also has a small performance hit compared to statically linked programs when opening the program as it still has to link the library in order to run.
Now that we know the differences, why should I use them?
There's one very simple question you should ask when deciding if you need to use a library: Do you have multiple pieces of code that are going to be used in several different programs that you don't want to rewrite over and over? If yes, then use a library. Just like physical libraries of books, a programming library is used for organizational purposes. They prevent you from having to rewrite the same code over and over every time you make a program that can use it. If you are curious about what dynamic libraries are used in a certain program, you can use the comman ldd.
Libraries sound awesome, so how do I make one?
Creating static and dynamic libraries have the same basic process, but are still slightly different. First off you are going to need the code that you want inside of a library. These should all be in .c files. In my examples, I'm going to be using a collection of functions, each in their own .c files, that mimic functions from the C standard library. Next we need all of these .c files to be compiled down into object files. We can do this by passing -c as an argument to gcc when compiling. If you are making a dynamic library, you should also have the argument -fPIC when compiling these. This tells GCC that the code does not need to depend on it's position in memory (Position-Independent Code). After doing this successfully, you should have a .o object file for every .c file that you compiled. Now we need to put all of these object files into a "collection" or library. For static you just need to use the ar command to archive them into one file with the argument rc to index everything inside of it, you can also use ranlib to index it. Dynamic is a lot easier with only the command gcc -shared -o. You now have a usable library to do what you please with!
Okay, now how do I use my library?
To use your library is very simple! If it's a dynamic library, ensure that the library can be found by your system by putting it into a directory pointed to by LD_LIBRARY_PATH, or alternatively, add it's path to the variable directly. It is also often a good idea to use ldconfig to inform the system about the new libraries before use, though it is not always necessary. Then, for both kinds, all you gotta do is make sure you compile your program with the arguments -L. and -llibraryname. You can use the functions just like they were written inside of your program already!