Why use libraries?
As mentioned before, libraries allow us to store function definitions, aka pieces of code that will be use in our executable program. It makes the tedious task of compiling a huge number of source files together avoidable, isn’t it great? Libraries are made of object files, with the extension ‘.o’, and can be made on Linux with the gcc compiler. Then, it’s up to us if we want to create a static or shared library.
How libraries work:
Once the libraries are created, they can be linked with the file containing the main function, or entry point, with gcc. Then, the code of the functions used in the program will be linked into the executable program, and it will be ready to run!
How to create libraries:
Let’s use as an example the file “my_file.c”. In both cases, we need to create object files first. This is done with the following commands:
$ gcc -c my_file.c
$ gcc -c -fPIC my_file.c
The ‘-c’ option makes sure the compilation process stops before the linker, and creates the ‘my_file.o’ file (see my article about compilation).
We use an additional flag for dynamic libraries: ‘-fPIC’ or ‘-fpic’. This makes the code in the library position independent. PIC is code that works no matter where it is placed in memory. Why does it matter? Because several programs can use the same shared library, the library will have different addresses in memory for each program. And we still want our programs to have access to the code wherever it is stored.
Now we can create the ‘mylib’ library with our object file. Here’s how:
$ ar rc libmylib.a my_file.o
$ gcc -shared -o libmylib.so my_file.o
In the first case, we use the command ar to create a ‘.a’ file (a stands for archive), and in the second case we use gcc with flags ‘-shared’, and of course ‘-o’ because we compile from an object file, to create a ‘.so’ file (so is for shared object).
How to use libraries:
Now that we have our library, we have to use is to compile and create our program. Let’s say our entry point is in the ‘main.c’ file, and we want to name our program ‘test’. Here’s the command to compile the program with our library in both cases:
$ gcc -L. main.c -lmylib -o test
The ‘-L’ flag tells the compiler where it needs to look for the library, so in this case where the library is in the current working directory, we just use a dot. the ‘-lmylib’ tells the compiler to link the code in main.c with the code in the library my_lib. Finally, the ‘-o’ flag allows us to give a name to the executable, in this case it will be ‘test’.
This is where dynamic libraries differ from static. With a static library, we can just run the code now. But with a dynamic library, it won’t work. A useful tool to show this is ldd, a command that prints shared libraries dependencies. In our case, the output of ‘ldd test’ will contain a line that says:
libmylib.so => not found
This means the loader will not be able to find the library at runtime, so we need to place it in a standard location. This is done by updating the LD_LIBRARY_PATH environment variable and prepending our working directory to its existing value. Here’s a simple command to do so:
$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
Let’s try ‘ldd test’ again, and the output will be:
libmylib.so => ./libmylib.so (0x00007fd4bf2d9000)
On top of ldd for the dependencies, we can use the command ‘nm’ to check the symbols of a dynamic library. These symbols include the functions that are defined in the library. For dynamic libraries, we use the -D flag, like this:
$ nm -D libmylib.so
Okay, now that we’re sure that the dynamic library has been created and is usable, we can run our program by typing ‘./test’ in our command line.
What are the differences between static and dynamic libraries:
In programming, a library is a collection of pre-compiled pieces of code that can be reused in a program. Libraries simplify life for programmers, in that they provide reusable functions, routines, classes, data structures and so on
which they can be reused in the programs.
Static Libraries : A Static library or statically-linked library is a set of routines, external functions and variables which are resolved in a caller at compile-time and copied into a target application by a compiler, linker, or binder, producing an object file and a stand-alone executable. This executable and the process of compiling it are both known as a static build of the program. Historically, libraries could only be static.
They are usually faster than the shared libraries because a set of commonly used object files is put into a single library executable file. One can build multiple executables without the need to recompile the file. Because it is a single file to be built, use of link commands are simpler than shared library link commands, because you specify the name of the static library.
Shared Libraries :
Shared libraries are .so (or in Windows .dll, or in OS X .dylib) files.
These are linked dynamically simply including the address of the library (whereas static linking is a waste of space). Dynamic linking links the libraries at the run-time. Thus, all the functions are in a special place in memory space, and every program can access them, without having multiple copies of them.
What are the advantages and drawbacks of each of them:
Static and dynamic linking are two linking mechanisms. The main difference between static and dynamic linking is that static linking copies all library modules used in the program into the final executable file at the final step of the compilation while in dynamic linking, the linking occurs at run time when both executable files and libraries are placed in the memory.