Now let s try our test application again, this time using a shared library instead of a static library. The process is essentially just as simple. Let s first build a shared library using our initapi.o and randapi.o objects. One change is necessary when building source for a shared library. Since the library and application are not tied together as they are in a static library, the resulting library can t assume anything about the binding application. For example, in addressing, references must be relative (through the use of a GOT, or Global Offset Table). The loader automatically resolves all GOT addresses as the shared library is loaded. To build our source files for position-independence, we use the PIC option of gcc :
$ gcc -fPIC -c initapi.c $ gcc -fPIC -c randapi.c
This results in two new object files containing position-independent code. We can create a shared library of these using gcc and the -shared flag. This flag tells gcc that a shared library is to be created:
$ gcc -shared initapi.o randapi.o -o libmyrand.so
We specify our two object modules with an output file ( -o ) as our shared library. Note that we use the .so suffix to identify that the file is a shared library (shared object).
To build our application using the new shared object, we link the elements back together as we did with the static library:
$ gcc test.c -L. -lmyrand -o test
We can tell that our new image is dependent upon our shared library by using the ldd command. The ldd command prints shared library dependencies for the given application. For example:
$ ldd test libmyrand.so => not found libc.so.6 => /lib/tls/libc.so.6 (0x42000000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) $
The ldd command identifies the shared libraries that will be used by test . The standard C library is shown ( libc.so.6 ) as is the dynamic linker/loader ( ld-linux.so.2 ). Note that our libmyrand.so file is shown as not found. It s present in the current subdirectory with our application, but it must be explicitly specified to GNU/Linux. We do this through the LD_LIBRARY_PATH environment variable. After exporting the location of our shared library, we try our ldd command again:
$ export LD_LIBRARY_PATH=./ $ ldd test libmyrand.so => ./libmyrand.so (0x40017000) libc.so.6 => /lib/tls/libc.so.6 (0x42000000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) $
We specify that our shared libraries are found in the current directory ( ./ ), and then after performing another ldd , our shared library is successfully found.
If we had tried to execute our application without having done this, a reasonable error message would have resulted, telling us that the shared library could not be found:
$ ./test ./test: error while loading shared libraries: libmyrand.so: cannot find shared object file: No such file or directory. $