When I create a library on Linux, I use this method:
The way you're supposed to form the x.y.z version is like this:
So the x and z numbers are very important for the system to determine if a given app can use a given library, given what the app was compiled against. The y number is mainly for tracking bug fixes.
According to Wheeler, we have the real name
, the soname
and the linker name
:
Real name libfoo.so.1.2.3
Soname libfoo.so.1
Linker name libfoo.so
The real name
is the name of the file containing the actual library code. The soname
is usually a symbolic link to the real name
, and its number is incremented when the interface changes in an incompatible way. Finally, the linker name
is what the linker uses when requesting a library, which is the soname without any version number.
So, to answer your last question first, you should use the soname
, libhelloworld.so.1
, for the linker option when creating the shared library:
g++ ... -Wl,-soname,libhelloworld.so.1 ...
In this document, Kerrisk provides a very brief example on how to create a shared library using standard naming conventions. I think both Kerrisk and Wheeler are well worth a read if you want to know more about Linux libraries.
There is some confusion regarding the intent and purpose of each of the numbers in the real name
of the library. I personally think that the Apache Portable Runtime Project does a good job of explaining the rules for when each number should be incremented.
In short, the versioning numbers can be thought of as libfoo.MAJOR.MINOR.PATCH
.
PATCH
is incremented for changes that are both forwards and backwards compatible with other versions.MINOR
should be incremented if the new version of the library is source and binary compatible with the old version. Different minor versions are backwards compatible, but not necessarily forwards compatible, with each other. MAJOR
is incremented when a change is introduced that breaks the API, or is otherwise incompatible with the previous version. What this means is that PATCH
releases may only differ internally, for example in the way a function is implemented. Changing the API, the signature of public functions, or the interpretation of function parameters is not allowed.
A new MINOR
release may introduce new functions or constants, and deprecate existing functions, but may not remove anything that is externally exposed. This ensures backwards compatibility. In other words, a minor release 1.12.3
may be used to replace any other 1.12.x
or earlier version, such as 1.11.2
or 1.5.0
. It is not a drop in replacement for 1.16.1
though, since different minor versions are not necessarily forward compatible.
Any kind of change can be made with the release of a new MAJOR
version; constants may be removed or changed, (deprecated) functions may be removed, and of course, any changes that would normally increment the MINOR
or PATCH
number (though it might be worth it to backport such changes to the previous MAJOR
version also).
Of course, there are factors that can complicate this further; you might have developed your library so that the same file may hold multiple versions simultaneously, or you might use libtool
's convention of current:revision:age
. But that's a discussion for another time. :)
From an old email I sent to a colleague about this question:
Let's look at libxml as an example. First of all, shared objects are stored in /usr/lib with a series of symlinks to represent the version of the library availiable:
lrwxrwxrwx 1 root root 16 Apr 4 2002 libxml.so -> libxml.so.1.8.14
lrwxrwxrwx 1 root root 16 Apr 4 2002 libxml.so.1 -> libxml.so.1.8.14
-rwxr-xr-x 1 root root 498438 Aug 13 2001 libxml.so.1.8.14
If I'm the author of libxml and I come out with a new version, libxml 2.0.0 that breaks interface compatiblity with the previous version, I can install it as libxml.so.2, and libxml.so.2.0.0. Note that it is up to the application programmer to be responsible about what he links to. If I'm really anal, I can link directly to libxml.so.1.8.14 and any other version will result in my program not running. Or I can link against libxml.so.1 and hope that the libxml developer doesn't break symbol compatibility on me in the 1.X version. Or if you don't care and are reckless, just link to libxml.so and get whatever version there is. Sometimes, when enough people do this, the library author has to get creative with later versions. Hence, libxml2:
lrwxrwxrwx 1 root root 17 Apr 4 2002 libxml2.so.2 -> libxml2.so.2.4.10
-rwxr-xr-x 1 root root 692727 Nov 13 2001 libxml2.so.2.4.10
Note that there's no libxml2.so in this one. Looks like the developer got fed up with irresponsible application developers.
The primary advantage of this method is easily letting users know which version of the library they have. For example, if I know a bug I'm getting was fixed in 1.0.4 I can easily check what version of the library I am linking against, and know if that's the right way to fix the bug.
This number is referred to as the "shared object version" or "soversion" and is part of the ELF binary standard. IBM has a good overview of ELF at http://www.ibm.com/developerworks/power/library/pa-spec12/.
There are several ways to name libs:
See:
https://blogs.oracle.com/ali/entry/how_to_name_a_solaris http://www.gnu.org/software/libtool/manual/libtool.html#Versioning