So what are they?
A shared library is a library that dynamically links during compilation when a user compiles a .c file. Static and dynamic linking are two processes of collecting and combining multiple object files in order to create a single executable file. The main difference between the two is the type of linking they do when creating an executable file.
Contrary to a static library, a dynamic library performs the linking process as a program is executed in Linux. Moreover, dynamic libraries are loaded into memory by programs when they are executed. During compilation, a shared libraries machine code is cached locally and has a version control of sorts that keeps track of what the most recent changes are to the file.
Let’s say you create a shared library and then run some tests. Next, you decide to add some more code to your functions in the shared library. Well, when you recompile, the compilation process just appends the recent changes to the cache versus having to recompile everything all over again as you would in a static library creation.
How to create a shared library?
So lets say we have a couple of files that we want to turn into a shared library…
file0.c file1.c file2.c and a header file
each of those functions serve their own purpose and their prototypes are included in the header file.
To create the shared library lets run this command
$ gcc -fPIC -Wall -Werror -Wextra -pedantic *.c -shared -o libfile.so
-fPICflag enables position independent code, which allows the code to be located at any virtual address at runtime.
-Wallenables all warnings our compiler could throw.
-Werrorturns all warnings into errors (won’t compile until errors fixed).
-Wextraensures that type comparisons are valid.
-pedanticmakes sure that the code follows ISO standards.
-sharedflag indicates that we want to create a shared library which has the file extension
-oflag allows us to name the output file ourselves.
- Final result:
Why are they useful?
So going back to our files example in the previous section let’s say we created another file called
file3.c that relies on another file’s prototype. We want to add this new code to the repository we have but we need to compile it first. We would want to use a dynamic library since we are probably going to be adding more files in the future. See below:
$ gcc -Wall -Werror -Wextra -pedantic -L. file3.c libfile -o foo
-L.tells the linker that the library is located in the current directory.
file3.cis the file that references the shared library to execute our program in the
-libfileflag is the shared library we want to use.
-oflag is to create an executable filename
foothat references library
Next, we need to set our environment variable
LD_LIBRARY_PATH to our
.so file so that the compiler can link during runtime. See below:
$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
Next, we need to install it in our object files directory on our Linux machine:
$ export LD_LIBRARY_PATH=$HOME/lib:$LD_LIBRARY_PATH
How is it different than a static library?
Static libraries are fast and all prototypes are isolated to one file, but, you have to constantly load the file during compilation. Also, the executable file is larger in size since that library is included in it. This makes it a great choice for embedded systems type applications because the entire programs “ecosystem” needs to reside in one area. For example, a pacemaker is surgically installed in a human and the device needs access to the entire library since it will be performing operations (no pun intended :) ). You need to entire library to be linked to your executable file and all located in the memory of the device now implanted inside of the human.
Dynamic libraries have a slower execution time and are prone to compatibility issues, but, they are really fast in the compilation time and make the executable file smaller in size (since they don’t have that massive library file to create tons of overhead). This could have advantages in embedded systems when there is a connection to the updated files and the executable needs to be size conscious.