How to link with specific name (version) of a shared library - linux

I searched this problem here and find some similar question but there solutions not work for me. Here is my problem:
My application is compiling with shared library of openldap-2.3. Openldap has /usr/lib/libldap-2.3.so.0 which is linked to /usr/lib/libldap-2.3.so.0.2.31. I passed -lldap option to gcc, which linked the libldap-2.3.so.0 file to my application.
But i want to link with specific name like libldap.so. Please correct me, in future if i change the openldap version to 2.4 in development system, it will then link to the libldap-2.4.so.XXX version.
So How can I link my application to specific name, so that it will always look for same name like libldap.so.
NOTE: I created a softlink of /usr/lib/libldap-2.3.so.0 as /usr/lib/libldap.so and then pass the library name /usr/lib/libldap.so to compiler without -l then application compiled successfully without any linking error but still showing same libldap-2.3.so.0 in dependency.

The shared library mechanism (the link is oldish, but still relevant) in Unix works by linking the executable at build time against e.g. liba.so, which is a symbolic link to liba.so.1, which in turn is a link to liba.so.1.2. The executable then records liba.so.1 to load when starting up. If you update liba.so, it could be to liba.so.1.5 (no ABI change, first digit doesn't change), the links look like liba.so --> liba.so.1 --> liba.so.1.5, and your executable now uses 1.5 transparently. If the version goes to liba.so.2.0 (API change!), the system makes liba.so --> liba.so.2 --> liba.so.2.0. Your old executable still uses 1.5, any newly built program will now reference 2. All this works as long as 1.x stays around, obviously. Presumably your distribution offers library packages that can be installed in paralell, or some compat-liba-1 package for the benefit of old executables.

Related

What is the equivalent of forwarding DLLs in Linux/Unix?

I have a dynamic library that changes name across major versions i.e. version 3 was named lib3 and version 4 is named lib4, and so on.
I need to provide a shim lib3 that will allow an old application to use the new library in a transparent way, and most of the exported functions did not change across versions, so a forwarding DLL looks pretty good for the task on Windows.
Is there something equivalent on Linux/Unix?
The Linux equlivalent is rather easy. You can just use a symbolic link. For example, lib4 is the new library version, then you can create the following symbolic link:
ln -s lib4 lib3
Now, every time a program will need lib3 will automatically load lib4 as long as the interface
exported by the new version is equal to the old version, the program will not notice the difference.
I hope this helps. Let me know if you need more info.

making gcc prefer static libs to shared objects when linking?

When linking against libraries using the -l option (say -lfoo), gcc will prefer a shared object to a static library if both are found (will prefer libfoo.so to libfoo.a). Is there a way to make gcc prefer the static library, if both are found?
The issue I'm trying to solve is the following: I'm creating a plugin for an application (the flight simulator called X-Plane), with the following constraints:
the plugin is to be in the form of a 32 bit shared object, even when running on a 64 bit system
the running environment does not provide a convenient way to load shared objects which are not in the 'normal' locations, say /usr/lib or /usr/lib32:
one cannot expect the user to set LD_PRELOAD or LD_LIBRARY_PATH to find shared objects shipped with my plugin
the X-Plane running environment would not add my plugins directory to ``LD_LIBRARY_PATH, before dynamically loading the plugin shared object, which would allow me to ship all my required shared objects alongside my plugin shared object
one cannot expect 64 bit users to install 32 bit shared objects that are non-trivial (say, are not included in the ia32-libs package on ubuntu)
to solve the above constraints, a possible solution is to link the generated shared object against static, 32 bit versions of all non-trivial libraries used. but, when installing such libraries, usually both static and dynamic versions are installed, and thus gcc will always link against the shared object instead of the static library.
of course, moving / removing / deleting the shared objects in question, and just leaving the static libraries in say /usr/lib32, is a work-around, but it is not a nice one
note:
yes, I did read up on how to link shared objects & libraries, and I'm not trying to creatae a 'totally statically linked shared object'
yes, I tried -Wl,-static -lfoo -Wl,-Bdynamic, but didn't bring the expected results
yes, I tried -l:libfoo.a as well, but this didn't bring the expected results either
You can specify the full path to the static libs without the -l flag to link with those.
gcc ... source.c ... /usr/lib32/libmysuperlib.a ...
Just add the .a file to the link line without -l as if it were a .o file.
It's dated, but may work: http://www.network-theory.co.uk/docs/gccintro/gccintro_25.html
(almost end of the page)
"As noted earlier, it is also possible to link directly with individual library files by specifying the full path to the library on the command line."

Linking with a different .so file in linux

I'm trying to compile a piece of software which has the standard build process e.g.
configure
make
make install
The software requires a library e.g. libreq.so which is installed in /usr/local/lib. However, my problem is I'd like to build the software and link it with a different version of the same library (i have the source for the library as well) that I've installed in /home/user/mylibs.
My question is, how do I compile and link the software against the library in /home/user/mylibs rather than the one in /usr/local/lib
I tried setting "LD_LIBRARY_PATH" to include /home/user/mylibs but that didn't work.
Thanks!
When you have an autoconf configure script, use:
CPPFLAGS=-I/home/user/include LDFLAGS=-L/home/user/mylibs ./configure ...
This adds the nominated directory to the list of directories searched for headers (usually necessary when you're using a library), and adds the other nominated directory to the list searched for actual libraries.
I use this all the time - on my work machine, /usr/local is 'maintained' by MIS and contains obsolete code 99.9% of the time (and is NFS-mounted, read-only), so I struggle to avoid using it at all and maintain my own, more nearly current, versions of the software under /usr/gnu. It works for me.
Try using LD_PRELOAD set to your actual file.
LD_LIBRARY_PATH is for finding the dynamic link libraries at runtime. At compiling you should add -L parameters to gcc/g++ to specify in which directory the *.so files are. You also need to add the library name with -l<NAME> (where the library is libNAME.so).
Important! For linking you not only need the libNAME.so file but a libNAME.a is needed too.
When you run the application, don't forget to add the dir to the LD_LIBRARY_PATH.
When you added the /home/user/mylibs to the LD_LIBRARY_PATH did you add it to the front or end of the existing paths? The tokens are searched in-order so you will want yours to appear first in the list.
Also, many standard build environments that use configure will allow you to specify an exact library for each required piece. You will have to run ./configure --help but you should see something like --using-BLAH-lib=/path/to/your/library or similar.

Building Boost on Linux - library names

I am trying to build an application which depends on Boost. So I downloaded Boost 1_41_0 to my Linux box and followed the instructions found on the Boost site for Unix variants,
http://www.boost.org/doc/libs/1_41_0/more/getting_started/unix-variants.html.
They basically suggest that I run ./bjam install, which I did. The build completed successfully. However, the library names don't seem to match the Boost naming convention described both in the documentation above, and what is specified in the makefile of the application I am trying to build.
I noticed that there are a bunch of options that I can specify to bjam and I tried to play with those, but no matter what happens I can't seem to get it quite right. My understanding is that the libraries should go into the $BOOST_ROOT/lib directory. This is where the libraries show up, but named:
libboost_thread.a
libboost_thread.so
libboost_thread.so.1.41.0
I'd expect them to be named libboost_thread-gcc41-mt-d-1_41_0 or something similar.
I did try ./bjam --build-type=complete --layout=tagged and I see:
libboost_thread.a
libboost_thread-mt.a
libboost_thread-mt-d.a
libboost_thread-mt-d.so
libboost_thread-mt-d.so.1.41.0
libboost_thread-mt-s.a
libboost_thread-mt-sd.a
libboost_thread-mt.so
libboost_thread-mt.so.1.41.0
libboost_thread.so
libboost_thread.so.1.41.0
So, I am not sure if I should just make stage my -L directory? Is there any documentation which describe this in more detail?
The names was changed in 1.40.0 - see in release notes:
Build System
The default naming of libraries in
Unix-like environment now matches
system conventions, and does not
include various decorations.
They probably forgot to update this part in the build documentation.
There are two variables here. First is "install" vs. "stage" (default). "install" copies both libraries and headers into a directory -- /usr/local by default, and you can then remove source tree. "stage" puts libraries to "stage/lib", and you should add "-L /stage/lib -I " flags.
Second is --layout=versioned and --layout=system. It seems like you have discovered what they do already, and indeed, system is default since 1.40. The getting started guide fails to mention this, and I've added an action item to update it. Ideally, you should talk to the authors of the application to use the system naming of boost libraries. If that's not possible, then building with --layout=versioned is the only option.
From the Boost documentation at http://www.boost.org/doc/libs/1_35_0/more/getting_started/windows.html#library-naming, the convention is:
-mt Threading tag: indicates that the library was built with multithreading support enabled. Libraries built without multithreading support can be identified by the absence of -mt.
-d ABI tag: encodes details that affect the library's interoperability with other compiled code. For each such feature, a single letter is added to the tag:
Key Use this library when:
s linking statically to the C++ standard library and compiler runtime support libraries.
g using debug versions of the standard and runtime support libraries.
y using a special debug build of Python.
d building a debug version of your code.
p using the STLPort standard library rather than the default one supplied with your compiler.
n using STLPort's deprecated “native iostreams” feature.
For example, if you build a debug version of your code for use with debug versions of the static runtime library and the STLPort standard library in “native iostreams” mode, the tag would be: -sgdpn. If none of the above apply, the ABI tag is ommitted.

Using ldconfig on Linux

Let's say I 've added a library foo.so.1.1.1 to a path that is included in /etc/ld.so.conf
When I run ldconfig on the system I get the links foo.so.1.1 and foo.so.1 to foo.so.1.1.1
How can I change the behavior to also get the foo.so link to foo.so.1.1.1?
ldconfig looks inside all shared objects that it finds, to look for the soname. It then creates a link using that soname as the name of the link. It's conventional (but far from universally done) for the soname to be the name and major version of the library, so your library foo.so.1.1 will have a soname of foo.so.1 and ldconfig will make a link called that.
No part of the run-time system looks for or knows anything about the name foo.so. That's used when you link your programs to the library. There's no point in having that link unless you also have all the other development files (headers etc) for the library, so there's no point in ldconfig automatically creating it. And since the name of the link to use is only another convention, and in this case isn't stored inside the file at all, there's no way for ldconfig to know what name to create.
Normally this would be created manually, in the install target of the Makefile; when a library is packaged for a linux distribution the link normally lives in the -dev package along with the header files.
Just make the symlink yourself:
ln -s /usr/lib/foo.so.1.1.1 /usr/lib/foo.so
Note that for applications to use libraries in this manner, they need to be explicitly linked against the unversioned shared object. IE: this is a mechanism to bypass the dynamic loader's version matching system completely.

Resources