I'm building a shared object file from a group of C++ source files using GCC. All the example tutorials on building .so
files show the file created with a version number after the .so
suffix. For example:
gcc -shared -Wl,-soname,libmean.so.1 -o libmean.so.1.0.1 calc_mean.o
This would produce the .so
file libmean.so.1.0.1
Additionally, if I browse the /usr/lib
directory on my local machine, I see that many of the .so
files have version numbers at the end.
However, when I compile a shared object file and place it in /usr/lib
, the linker is unable to find it if I put a version number at the end. If I remove the version number, it works fine. I really don't care about putting a version number or not, I just don't understand why this seems to be a common convention, and yet this causes the shared library to not work with the linker. So, what's going on here? Why is there a convention to place the version number at the end of an .so
file name?
The version number is appended so you can have multiple incompatible library versions coexisting in the system. You should increment the major version number (the number in soname
) every time you change the API in an incompatible way (assuming the previous version is installed and used in the system, of course).
The 2nd and 3rd numbers in the file name allows for multiple minor revisions of the library in the system, switchable system-wide with a simple symlink update.
At link time you can give the .so
file name as a linker argument, instead of -l
option. ldd is smart enough to extract the soname
from it, the binary linked this way uses it to find the library.
For example, let's compile the library and test binary using it:
czajnik@czajnik:~/z$ gcc -shared -Wl,-soname,libtest.so.2 -o libtest.so.2.3.4 a.c
czajnik@czajnik:~/z$ gcc -o test b.c -L. ./libtest.so.2.3.4
You can use ldd to verify, that the binary now looks for libtest.so.2
:
czajnik@czajnik:~/z$ LD_LIBRARY_PATH=. ldd ./test
linux-gate.so.1 => (0x002c1000)
libtest.so.2 => not found
libc.so.6 => /lib/libc.so.6 (0x00446000)
/lib/ld-linux.so.2 (0x00a28000)
It obviously can't find it, but that's what the symlink is for:
czajnik@czajnik:~/z$ ln -s libtest.so.2.3.4 libtest.so.2
czajnik@czajnik:~/z$ LD_LIBRARY_PATH=. ldd ./test
linux-gate.so.1 => (0x00d75000)
libtest.so.2 => ./libtest.so.2 (0x00e31000)
libc.so.6 => /lib/libc.so.6 (0x00a5e000)
/lib/ld-linux.so.2 (0x00378000)
Update: All of the above is true, yet I wasn't myself aware of the meaning of the 3rd component of the version number. Until recently, I believed it is simply a patch number (or similar thing). Wrong! For libtool it has a special meaning.
The 3rd component turned out to be age field, which says how many major versions are backward compatible with the current one.
Recommended reading:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With