Multiple versions of same the same library in LD_LIBRARY_PATH [duplicate] - linux

Windows provides the resource file for version information for an application and DLL. The resource file includes information like version, copyright and manufacturer.
We have a shared library and would like to add version information.
How can we do it on Linux with a shared library?

The short version is that you do this via the soname of the library. Read chapter 3 at http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html as well as chapter 3.3 ABI Versioning at http://www.akkadia.org/drepper/dsohowto.pdf

The best way to handle this is using libtool, which does the versioning for you.
Essentially, version information is not (or not primarily, don't know from my head) encoded in the library itself, but rather in its filename. Version numbers are normally given in three-dot format, with the major number increasing for each break in downward ABI compatibility, the middle for breaks in upward ABI compatibility, and the minor for patches that did not change the ABI.
Like qdot noted, symlinks in the lib directory provide the essential versioning. There is a symlink without a version number (libfoo.so) for the currently installed development headers, a symlink with a major number for each installed major version (libfoo.so.1) and a real file with the full version number. Normally, programs are linked to use libfoo.so.1 at runtime so that multiple major versions may coexist.

Linux uses the following strategy - you (the system maintainer) provide symlinks from a 'specific' shared library file, like this:
lrwxrwxrwx 1 root root 16 2011-09-22 14:36 libieee1284.so -> libieee1284.so.3
lrwxrwxrwx 1 root root 20 2011-09-22 14:36 libieee1284.so.3 -> libieee1284.so.3.2.2
-rw-r--r-- 1 root root 46576 2011-07-27 13:08 libieee1284.so.3.2.2
This way, developers can link either against -lieee1284 (any version ABI), or libieee1284.so.3 or even to the specific release and patch version (3.2.2)

Related

How to build glibc with reduced size?

I'm trying to download glibc 2.23 sources and build them on my Ubuntu system.
I need to build that specific version from sources for getting modified version of glibc customized for my research, and it will be used only within my research apps using the loader environment variables (e.g., LD_PREDLOAD or LD_LIBRARY_PATH).
But, when building it as following, I got a huge file as an output (libc.so weights about 11MB):
download the sources to some local dir (let's say /tmp/glibc/)
create new directory for build results (/tmp/glibc/build)
run configure from build dir:
< build-dir >$ ../configure --prefix=< build-dir >
As a result, the build process will produce libc.so file under build-dir with a size of 11MB.
Is there anyway to reduce the size of the built libc.so?
p.s.
Here are my system details:
Linux version 4.4.0-93-generic (buildd#lgw01-03) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) ) #116-Ubuntu SMP Fri Aug 11 21:17:51 UTC 2017
Thanks :)
Building glibc from source could be a bad idea. See this and some comments there. Its current version is GNU libc 2.26... Consider instead upgrading your entire Ubuntu distribution (Ubuntu 17.10 should be released in a few weeks, end of October 2017)
../configure --prefix= build-dir
is a misunderstanding of the role of --prefix in autoconf-ed software. It relates to where the software is installed, not to its build directory.
(and I don't know exactly what should be your --prefix since libc is so essential to your system, perhaps it should be --prefix=/ but you should check carefully)
Is there any way to reduce the size of the built libc.so?
You might use (very carefully) strip(1), but you risk breaking your system.
And you might not care about reducing the size of libc since it is used (and shared) by almost every software on your Linux system!
BTW, consider also musl-libc. It can cohabit nicely with GNU glibc, and in practice is used only by programs built with musl-gcc (provided by it).
If you are doing some research, it would be reasonable to work in a chroot(2)-ed environment. See also schroot. You could install with the help of make install DESTDIR=/tmp/instmylibc then copy that /tmp/instmylibc appropriately. Read more about autoconf
PS. Be sure to at least back up your important data before such dangerous experimentations. I don't think that the size of your libc.so should be a significant concern. But you need to use chroot, perhaps with the help of debootstrap during installation of the chrooted environment.

How to do versioning of shared library?

Windows provides the resource file for version information for an application and DLL. The resource file includes information like version, copyright and manufacturer.
We have a shared library and would like to add version information.
How can we do it on Linux with a shared library?
The short version is that you do this via the soname of the library. Read chapter 3 at http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html as well as chapter 3.3 ABI Versioning at http://www.akkadia.org/drepper/dsohowto.pdf
The best way to handle this is using libtool, which does the versioning for you.
Essentially, version information is not (or not primarily, don't know from my head) encoded in the library itself, but rather in its filename. Version numbers are normally given in three-dot format, with the major number increasing for each break in downward ABI compatibility, the middle for breaks in upward ABI compatibility, and the minor for patches that did not change the ABI.
Like qdot noted, symlinks in the lib directory provide the essential versioning. There is a symlink without a version number (libfoo.so) for the currently installed development headers, a symlink with a major number for each installed major version (libfoo.so.1) and a real file with the full version number. Normally, programs are linked to use libfoo.so.1 at runtime so that multiple major versions may coexist.
Linux uses the following strategy - you (the system maintainer) provide symlinks from a 'specific' shared library file, like this:
lrwxrwxrwx 1 root root 16 2011-09-22 14:36 libieee1284.so -> libieee1284.so.3
lrwxrwxrwx 1 root root 20 2011-09-22 14:36 libieee1284.so.3 -> libieee1284.so.3.2.2
-rw-r--r-- 1 root root 46576 2011-07-27 13:08 libieee1284.so.3.2.2
This way, developers can link either against -lieee1284 (any version ABI), or libieee1284.so.3 or even to the specific release and patch version (3.2.2)

Linking 3rd party shared libraries without soname, linker name

Installing liboost-dev on Debian Squeeze gives me several libraries like /usr/lib/libboost_thread.so.1.42.0, but no libboost_thread.so. Now I can't link using the -l flag of gcc / ld because the names don't end in .so.
I notice that /usr/lib has plenty of other libraries of the form libfoo.so.N without a libfoo.so, so this isn't peculiar to Boost. I ended up adding libboost_thread.so.1 and libboost_thread.so symlinks links by hand. (The man page for ldconfig suggests it will add the links, but it didn't do anything).
Everything works fine, but it feels dirty. What should I have done?
use some more specific linker option I haven't found yet (at the cost of making my makefiles depend on a specific version number).
just add the symlinks by hand (at the risk of subverting package management).
some other Debian 'right way' to do it.
You installed the run-time package libboost-thread1.42.0 but the development package libboost-thread-dev (or even the catch-all package libboost-all-dev.
Once you have the corresponding -dev package, linking will work. That is a general feature of most Linux distribution---you almost never want to mess with the symlinks by hand.
Edit: In response to your comment:
edd#max:~$ ls -l /usr/lib/libboost_thread.*
-rw-r--r-- 1 root root 176324 2010-10-21 00:56 /usr/lib/libboost_thread.a
lrwxrwxrwx 1 root root 25 2011-05-14 10:17 /usr/lib/libboost_thread.so -> \
libboost_thread.so.1.42.0
-rw-r--r-- 1 root root 88824 2010-10-21 00:56 /usr/lib/libboost_thread.so.1.42.0
edd#max:~$ dpkg -S /usr/lib/libboost_thread.so
libboost-thread1.42-dev: /usr/lib/libboost_thread.so
edd#max:~$
Clearly the package management system created the links, and owns them.
Dirk's answer is correct about the general principle but there seems to be an extra trap for the unwary with the boost packaging.
Normally the headers and the library symlink are in the same package, so you get the library symlink without thinking about it. However with boost "libboost<version>-dev" provides the headers but "libboost-<lib><version>-dev" provides the shared library symlink. So if you only install the former you get stuff compiling but not linking.

whats are *.so.*.* libs

When I do ls -l in /usr/lib I see lots of libs with "sameName.so.*.*" extension.
What is the significance of these extensions?
Why softlinks are created? what are their use?
One example will help a lot in understanding.
This is a trick used to version shared object files. It's a way of avoiding the dreaded DLL hell which came about because of lazy linking.
The advantage of lazy linking (or late binding) is that components of your executable can be changed without actually re linking those executables. This allows for bug fixes in third party components without having to ship a new executable, among other things.
The disadvantage is exactly the same as the advantage. Your executable can find that assumptions it made about the underlying libraries have been changed and this is likely to cause all sorts of issues.
Versioning of shared objects is one way to avoid this. Another would be to not share objects at all but that also has pros and cons which I won't get into here.
By way of example, let's say you have version 1 of xyz.so. You have a file and a symbolic link to that file:
pax> ls -al xyz*
-rw-r--r-- 1 pax paxgroup 12345 Nov 18 2009 xyz.so.1
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so -> xyz.so.1
Now, when you create an executable file exe1, linking it with xyz.so, it will follow the symbolic link so that it stores xyz.so.1 in the executable as the thing it needs to load at runtime.
That way, when you upgrade the shared library thus:
pax> ls -al xyz*
-rw-r--r-- 1 pax paxgroup 12345 Nov 18 2009 xyz.so.1
-rw-r--r-- 1 pax paxgroup 67890 Nov 18 2009 xyz.so.2
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so -> xyz.so.2
your original executable exe1 will still load version 1 of the shared object.
However, any executables you create now (such as exe2) will be linked with version 2 of the shared object.
The actual implementation details may vary somewhat (I'm basing my answer on earlier UNIXes and Linux appears to do versioning a little more intelligently than just following symbolic links). IBM developerWorks has a nice article on how it's done here.
When you create a shared object, you give it both a real name and an soname. These are used to install the shared object (which creates both the object and a link to it).
So you can end up with the situation:
pax> ls -al xyz*
-rw-r--r-- 1 pax paxgroup 12345 Nov 18 2009 xyz.so.1.5
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so.1 -> xyz.so.1.5
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so -> xyz.so.1
with xyz.so.1.5 possessing the SONAME of xyz.so.1.
When the linker links in xyz.so, it follows the links all the way to xyz.so.1.5 and uses its SONAME of xyz.so.1 to store in the executable. Then, when you run the executable, it tries to load xyz.so.1 which will point to a specific xyz.so.1.N (not necessarily version 1.5).
So you could install xyz.so.1.6 and update the xyz.so.1 link to point to it instead and already-linked executables would use that instead.
One advantage of this multi-layer method is that you can have multiple potentially incompatible libraries of the same name (xyz.so.1.*, xyz.so.2.*) but, within each major version, you can freely upgrade them since they're supposed to be compatible.
When you link new executables:
Those linking with xyz.so will get the latest minor version of the latest major version.
Others linking with xyz.so.1 will get the latest minor version of a specific major version.
Still others linking with xyz.so.1.2 will get a specific minor version of a specific major version.
It's a versioning scheme for shared libraries. Every library should have 3 names:
Real name: the actual library name, libfoo.so.1.2.3
"SONAME": the name recorded in the executable, and the name dynamic linker looks for, libfoo.so.1.2. This name is actually written inside the library binary itself, and will be recorded in the executable at link time. It is usually a symlink to library's real name (usually latest version).
Linker name: the name you give to the linker when building your program. Usually links to the latest SONAME.
Example
Say you have libfoo version 1 installed: libfoo.so -> libfoo.so.1.0 -> libfoo.so.1.0.0. You build your program bar with -lfoo. it now links to libfoo and will load libfoo.so.1.0 at runtime due to SONAME. Then you upgrade to a patched but binary-compatible libfoo.so.1.0.1 by replacing real binary. bar still links to libfoo.so.1.0 and doesn't need to be rebuilt.
Now imagine you want to build a new program baz that takes advantage of incompatible changes in libfoo v1.1. You install new version and your system now have two versions installed in parallel:
libfoo.so.1.0 -> libfoo.so.1.0.1
libfoo.so -> libfoo.so.1.1 -> libfoo.so.1.1.0
Note linker name was updated to the latest version (this is the version corresponding to the headers you installed in /usr/include).
You build baz, and it links to libfoo.so and loads libfoo.so.1.1 at runtime. Not that bar still runs against libfoo.so.1.0 and doesn't need to be updated.

How do applications resolve to different versions of shared libraries at run time?

I'm a noob to how shared libraries work on linux. I am trying to understand how do applications resolve different revisions of the same shared library at run-time on linux.
As far as I understand, a shared library has three "names", for example,
libmy.so.1.2 (real-name i.e. the actual obj file)
libmy.so.1 (SONAME, which is embedded in the actual obj file)
libmy.so (linker name, provided to the linker at link time and embedded in executable)
When you install the library via LDCONFIG, it will create the following symbolic links
(2) => (1)
(3) => (2)
Now lets say I compile another version of the same library with the following real-name,
libmy.so.2.0. The SONAME by guidelines would be libmy.so.2.0
At application link time what is the linker name that I would provide with the "-l" flag. Following the guidelines I read (http://www.dwheeler.com/program-library/Program-Library-HOWTO/x36.html), wouldn't it have to be libmy.so and if so, how will both versions of the obj file be distinguished ?
Versioning of shared objects works as follows:
When you create a shared object, you give it both a real name and an soname. These are used to install the shared object (which creates both the object and a link to it).
So you can end up with the situation:
pax> ls -al xyz*
-rw-r--r-- 1 pax paxgroup 12345 Nov 18 2009 xyz.so.1.5
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so.1 -> xyz.so.1.5
lrwxrwxrwx 1 pax paxgroup 0 Nov 18 2009 xyz.so -> xyz.so.1
with xyz.so.1.5 possessing the SONAME of xyz.so.1.
When the linker links in xyz.so, it follows the links all the way to xyz.so.1.5 and uses its SONAME of xyz.so.1 to store in the executable. Then, when you run the executable, it tries to load xyz.so.1 which will point to a specific xyz.so.1.N (not necessarily version 1.5).
So you could install xyz.so.1.6 and update the xyz.so.1 link to point to it instead and already-linked executables would use that instead.
One advantage of this multi-layer method is that you can have multiple potentially incompatible libraries of the same name (xyz.so.1.*, xyz.so.2.*) but, within each major version, you can freely upgrade them since they're supposed to be compatible.
When you link new executables:
Those linking with xyz.so will get the latest minor version of the latest major version.
Others linking with xyz.so.1 will get the latest minor version of a specific major version.
Still others linking with xyz.so.1.2 will get a specific minor version of a specific major version.
Now keep that last paragraph in mind as we examine your comment:
Now lets say I compile another version of the same library with the following real-name, libmy.so.2.0. The SONAME by guidelines would be libmy.so.2.0.
No, I don't believe so. The soname would be more likely to be libmy.so.2 so that you can make minor updates to the 2.x stream and get the latest behaviour.
At application link time, if you specify -lmy, the linker will search for a file named libmy.so. It will find this file, and link you executable with it. If this file is a symbolic link, then your application will be linked with the target of the symlink.
Application link time is the place to specify which version of the dynamic library you want to use with your application.
A complement to #paxdiablo's answer bullet one:
ldconfig doesn't set up the linker names; typically this is done during library installation, and the linker name is simply created as a symbolic link to the ``latest'' soname or the latest real name.
it means xxx.so will link to a latest minor version of the latest major version dynamic library file.
I think this explains why:
Those linking with xyz.so will get the latest minor version of the latest major version.
But I don't know how installation setup linker name and which tool make it(apt-get?)
Libs have different versions in the name.
Packages with name "lib" have only libs and have different versions in the name.
System will compile only with the latest library,
unless you define a different one.
The application uses only those libraries that it needs.
Check ldd , readelf.
Apps contain a link .so and .pc file, check rpm system for what.
https://fedoraproject.org/wiki/Packaging:Guidelines?rd=Packaging#Devel_Packages

Resources