C - Static libraries
In computer science, a library is a collection of non-volatile resources used by computer programs, often for software development. These may include configuration data, documentation, help data, message templates, pre-written code and subroutines, classes, values or type specifications.
Why do we use libraries?
The necessity of using libraries becomes from the problem that developed programs tend to grow longer, and it affects directly the compilation time.
Imagine that you crate a function, and every time you need to use it you have to rewrite the code in your program or copy paste it. It is not only non-efficient for the time that takes doing the same work more than once, also it is not because our program is going to be too long.
A solution for this is using headers, we can write our functions into .c files and just referenced by a header file in our main program and compiling with those .c files we can use these functions. But, it still being a solution if we need to use 20, 30 or 40 functions? In this case we need to compile with every .c file, and when we talk about a huge number of files it starts to be useless.
So, here is when we talk about libraries. Without entry into the specific definition in C of libraries, we could say that they are a collection of resources, in this case it would be shorter pieces of code with the functions that we need to use in our program.
In that order, the libraries are a good way of managing our projects, because we can combine source code into small units of related files, that can be used in our program without the tedious job of rewriting the code, copy paste it or compile with 40 .c files.
With the library we can link the 20, 30 or 40 files with the functions into one file (library) and just reference the library when we compile the program, and it is incredible because we do the same thing but now in a most efficient and ordered way.
How they work
On my previous blog I talked about the compilation process in C and the different steps of it.
As you can see, the fourth step of the compilation process is the Linker, and if you pay attention, on that step is the moment where the object code and libraries are integrated to the program.
A library is a file containing several object files, that can be used as a single entity in a linking phase of a program. Normally the library is indexed, so it is easy to find symbols (functions, variables and so on) in them. For this reason, linking a program whose object files are ordered in libraries is faster than linking a program whose object files are separate on the disk.
Static libraries are just collections of object files that are linked into the program during the linking phase of compilation.
How to create them
First, we need to put all the .c files with the functions in it in a directory, for example I have created two functions _islower and _putchar.
How I said before, a library contain object files, so the next step is converting the .c files to object code. As you can see in the picture above, we could do that with the third step of the compilation process in C (Assembler), and our output it’s going to be .o files.
And this is how our files look now.
Once we have the object files, we need to use the ar command, “ar” stands for archiver. This command can be used to create static libraries (which are actually archive files), modify object files in the static library, list the names of object files in the library, and so on.
In order to create a static library, we can use the command like this.
This command creates a static library named “libmy.a” and puts copies of the object files "_islower.o" and "_putchar.o" in it.
The “r” flag tells ar to replace older object files in the library, with the new object files.
领英推荐
The “c” flag tells ar to create the library if it doesn't already exist.
If the library file already exists, it has the object files added to it, or replaced, if they are newer than those inside the library.
Note: If we have a huge number of .o files we can use *.o to refer to all of them.
Ok, now we have already created our library but how do we know if our files with the functions are in it?
We can do it using ar with the command flag -t (dysplay a table listing the contents of archive, or those of the files listed in member... that are present in the archive).
Or we can do it with the command nm (The nm utility shall display symbolic information appearing in the object file, executable file, or object-file library named by file.)
After an archive is created, or modified, there is a need to index it. This index is later used by the compiler to speed up symbol-lookup inside the library, and to make sure that the order of the symbols in the library won't matter during compilation.
The command used to create or update the index is called “ranlib”, and is invoked as follows.
And finally, if we use the command nm with the flag -s we can see the index.
On some systems, the archiver (which is not always ar) already takes care of the index, so ranlib is not needed (for example, when Sun's C compiler creates an archive, it is already indexed).
How to use them
We have already talked about what static libraries are, how they work and how to create them. So, all that rest is talk about how we can use them.
The reason why we have created our library archive, is to use it in a program. This is done by adding the library's name to the list of object file names given to the linker, using a special flag, normally '-l'.
If our program is main.c.
Note that I omitted the "lib" prefix and the ".a" suffix when mentioning the library on the link command. The linker attaches these parts back to the name of the library to create a name of a file to look for. Note also the usage of the “-L”?flag, this flag tells the linker that libraries might be found in the given directory.
Some pros and cons of using static libraries
Pros: Static libraries are not required at runtime, so you do not need to include them when you distribute your executable.
At the moment that we have to compile, linking to a static library is generally faster than linking to individual source files.
Cons: If the library code is updated (for example, 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, so you have to recompile one by one.?