what the f*Lib.so?


I am a Software Engineering Student at Holberton School, San Francisco | contact me or follow me.

Share

:C language libraries, part 2, dynamic libraries

compiler: gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
environment: vagrant virtual machine with linux 14.04.5 LTS for Ubuntu
language: C language

For background information on the subject, it's helpful to understand what happens when C language files are compiled; for more information  on that, check out my other blog post: Computer Compilers: brief introduction, which helps to explain how the gcc compiler works. As this is a continuation of another blog post that I wrote, please refer to my post on libraries: what the f*Lib.a? for more on static libraries.  Here is a short summary from that blog:

why use libraries and how they work

Library files typically contain the code for functions that are most commonly used by an application or programmer, or that belong to a unique set of functions that together work to meet a larger end goal that can be used in a variety of different applications. Thus, libraries in C language help programmers save time by linking those common functions instead of having to hard code those same functions every time a programmer needs to use them in different applications and situations. Also, by keeping the most common functions separated into libraries, it helps programmers to stay organized. Programmers can share a set of functions in a libraries without adding any other of their unique code to the library as well. Another advantage is being able to modify library files without impacting your main() function or your executable file. For example, if a programmer ever updates the code from a library, it is possible to make these changes without effecting the executable files that uses the library's functions and without having to integrate the changes into all the files that use the libraries; this depends on the way one compiles a program and links the libraries. In the linking phase of gcc, which comes after the preprocessor phase when header files are actually copied into your source code, libraries are “linked” either dynamically or statically.

How to create dynamic libraries (linux only)

In the following code snippets, you will see how I have created a dynamic library and then how I used the dynamic library. Since I’m a student at Holberton School in San Francisco, and since their program teaches us students to create our own C libraries, which I find to be exceptionally useful, I will give them a shoutout in my below examples.

Source Code

First, listed here are my ‘.c’ files and functions with the unique header ‘.h’ file that I will use in place of the C standard library. I also used cat to show the code in each of the files.

$ ls
_strncpy.c  puts.c  holberton.h  _putchar.c
$ cat holberton.h
int _putchar(char c);
void _puts(char *s);
char *_strncpy(char *dest, char *src, int n);
$ cat _putchar.c
#include 
int _putchar(char c)
{
	return (write(1, &c, 1));
}
$ cat _strncpy.c
#include "holberton.h"
char *_strncpy(char *dest, char *src, int n)
{
	int j;
	for (j = 0; j < n && src[j] != 0; j++)
		dest[j] = src[j];
	for (; j < n; j++)
		dest[j] = 0;
	return (dest);
}
$ cat _puts.c
#include "holberton.h"
void _puts(char *str)
{
	int i;
	for (i = 0; str[i] != 0; i++)
		_putchar(str[i]);
	_putchar('n');
}

gcc

In the next example, I will use the commands gcc -c -fPIC *.c to create the object files and to store them into a library called libholberton.so. Dynamic libraries begin with "lib" and end with '.so' extensions.  Below I used the -c flag; the manual on gcc has this explaination for that flag: "Compile or assemble the source files, but do not link. The linking stage simply is not done.  The ultimate output is in the form of an object file for each source file."  If you read my post on the GNU compiler collection, you would remember that this means that the compiler goes through the preprocessor, compiler, and assembler.  The -fPIC flag is explained in the manual on gcc: "If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size of the global offset table. This option makes a difference on the m68k, PowerPC and SPARC. Position-independent code requires special support, and therefore works only on certain machines."

$ gcc -c -fPIC *.c
$ ls *.o
_strncpy.o  puts.o _putchar.o

confirmation

Next, I will run the command, nm. The manual page from linux states, "GNU nm lists the symbols from object files objfile". This command will give us an example of some of the object code files in the libholberton.so file, which is the name of the library, to verify success of our new library!  Static library files typically end with '.a' extension for "Archive" library verses '.so' extension standing for "Shared Object" library, or dynamic library.

$ nm libholberton.so | head

0000000000201040 B __bss_start
0000000000201040 b completed.6973
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000000650 t deregister_tm_clones
00000000000006c0 t __do_global_dtors_aux
0000000000200e08 t __do_global_dtors_aux_fini_array_entry
0000000000201038 d __dso_handle
0000000000200e18 d _DYNAMIC
0000000000201040 D _edata
0000000000201048 B _end

Next, we can use the ldd command to continue to verify that our library has been successfully created:

$ ldd holberton
	linux-vdso.so.1 =>  (0x00007ffd931c6000)
	libholberton.so => /home/vagrant/github.com/johncoleman83/holbertonschool-low_level_programming/example/libholberton.so (0x00007fa4dd432000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa4dd06d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa4dd634000)

configuration

The last step of creating the library is will be to ensure that your system is properly configured to be able to use your dynamic library.  You can do this by updating the environmental variable LD_LIBRARY_PATH to include the location of the directory where the library that we just created is stored, which in our case is the current working directory.  To do this, we use the export command in bash with the name of the environmental variable that you want to modify and the additional directory you want to add, which in this case, I prefer: $PWD for expansion of the environmental variable for the current working directory.  The location of the full directory path for the location of the library also happens to be in the above output from ldd; however, I like $PWD, as it is shorter type. This is the command that I used to add the new library to the list of environmental variables:

$ export LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH

Another way to configure the system to use the dynamic library is to open the /etc/ld.so.conf file as sudo and to add a newline at the end with the the path to the directory containing the library. In this case, we add the current working directory, which is listed above in the results from the command 'ldd', which is:

/home/vagrant/github.com/johncoleman83/holbertonschool-low_level_programming/example/libholberton.so.

Then you need to run ldconfig to rebuild the cache of the known libraries, and then verify that the library was added. Those two commands would be:

$ sudo ldconfig
$ ldconfig -p

how to use a dynamic libraries (linux only)

Now that the library has been created, let's make a C language program that uses functions from my custom library!  I'll create a file called 'main.c' with a main() function. This file will not include the C standard library <stdio.h>, and instead I will use my custom library with my custom functions.  Here is an example of a file containing a main() function that I will use for testing:

$ cat main.c
#include "holberton.h"
int main(void)
{
	char string1[] = "Holberton", string2[10], *p, i;
	p = _strncpy(string2, string1, 10);
	_puts("I just copied a string, see:");
	_puts(string2);
	return (0);
}

compile

when I compile the file, I will use the flags (or options) '-L.', '-l', and '-o' to include my library of functions and make the output file called 'holberton'. From reading the manual on gcc, we can learn that the '-L' flag instructs gcc to search for a library in the specified directory. Since, I added the '.', this means the current directory.  The '-l' flag/ option is described in the gcc manual as: -l library Search the library named library when linking. So, we specify the library libholberton.so; however, this option automatically prefixes the input code with 'lib' and suffixes it with the necessary suffix and so those specifications are unnecessary to include in the command to compile with gcc.

$ gcc main.c -L. -lholberton -o holberton

Finally, we execute the file to see the dynamic library work it's powerful C language beauty.

$ ./holberton
I just copied a string, see:
Holberton

what are the differences, advantages, and drawbacks between static and dynamic libraries?

To explain some of the differences, it's important to refer again to my post on the gcc compiler, which further explains the compilation process.  For this post, we have already discussed how gcc compiles into object files, which occurs after the preprocessor, compiler, and assembler steps.  The last phase of the compilation process is linking, and that concept is helpful in understanding the differences between static and dynamic libraries.

Linker

static linking

In the linking phase of compilation, for static libraries, the actual code from the library in binary form is copied and included into the final output executable file for the program being created during the compilation.  The static library therefore exists in a new location for each time it is used with compilation.  So, if you create 5 programs that use the static library, there will be 6 total instances of the library, 1 for the actual library, and 5 other copies that are included in the binary code of the executable file.  One advantage of this is that you do not need to keep a copy of the library to support the program that uses it because the program already has it included.  However, a disadvantage is that programs depending on static libraries, need to be updated and recompiled in order to account for any updates in the static library that they have.

dynamic linking

With dynamic linking, there is only 1 instance of the library, and so during compilation, the entire library is not copied, there is just a reference to the library's location in memory included with the executable file's binary code.  Therefore, the link to the library occurs during the runtime of the file.  If you have multiple programs depending on a dynamic library, each program refers to the same library during runtime; therefore the files that use dynamic libraries or shared libraries are smaller.  An advantage to this form of linking occurs when a dynamic library is updated, the program that depends on the library does not need to be altered or updated because it can still link to the library during runtime, and will utilize all the updates in the library.  Dynamic libraries take a little bit more time to load and begin running however because the linking occurs at runtime instead of during compilation.

Posted in C Programming Language, code, gcc, GNU, linux and tagged , , , .