Using ldconfig on Linux - 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.

Related

Which library does `Cmake` prefer to link to when invoking `target_link_libraries(target_name, library_name_without_postfix)`?

Both static and shared versions of a specific library are in the same folder, then which library does Cmake prefer to link to when invoking target_link_libraries(target_name, library_name_without_postfix)?
Why?
If target_link_libraries takes the library name in the 2nd parameter, it entirely depends on the linker. In your case, the link line will be translated to
-llibrary_name_without_postfix.
In this case, it will be searched in the standard path like, LD_LIBRARY_PATH, /etc/ld.so.conf or in the system path.
Since you didn't say anything about the location, I assume the library lives in the current build directory. And you have a command somewhere including the current build directory in the linker path using link_directories. In this case, the default link is dynamic.

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

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.

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."

Using library with different names within autoconf

I am trying to build an application with OpenSync 0.4 (0.3.9 indeed) dependency.
In the project's configure.ac the opensync library is written as libopensync1. However, this doesn't build on my Gentoo system. Changing libopensync1 to libopensync does fix the issue for me.
I searched with Google and found that libopensync1 is used in some distributions, while libopensync in others. So how to resolve this issue in configure.ac?
Thanks.
The macro AC_SEARCH_LIBS does what you need. (There is much heated debate about whether or not pkg-config should ever be used. If you choose to rely on it, ptomato gives a reasonable approach.) Simply add this to your configure.ac:
AC_SEARCH_LIBS([osync_mapping_new],[opensync1 opensync],[],
[AC_MSG_ERROR([can't find opensync])])
This will first look for a library named opensync1; if
it doesn't find that, it will look for opensync.
The primary drawback of using pkg-config is that most projects that
rely on it do not actually check if the data provided by the .pc
file is reliable, so configure may succeed but a subsequent build
will fail. It is always possible for a user to set PKG_CONFIG=true
when running configure and completely eliminate all of the data
provided by any associated .pc files, setting LIBS, CFLAGS, etc by
hand the 'old-fashioned' way.
The primary drawback of not using pkg-config is that the user
has to set LIBS, CFLAGS, etc. the old-fashioned way. In practice,
this is pretty trivial, and all pkg-config has done is move the
data from a single CONFIG_SITE file to separately maintained
.pc files for each package.
If you do use PKG_MODULE_CHECK, follow it up with a call to
AC_CHECK_LIB or AC_SEARCH_LIBS to validate the data in whatever
.pc file was located by PKG_CHECK_MODULES
I'm assuming that the place at which this occurs inside your configure.ac is inside a PKG_CHECK_MODULES call.
Looking at the libopensync sources, it seems that libopensync1 is the newer name, and libopensync is the old name. So, we'll use pkg-config macros to look for the newer name unless it doesn't exist.
Put this in your configure.ac:
# Check if libopensync1 is known to pkg-config, and if not, look for libopensync instead
PKG_CHECK_EXISTS([libopensync1], [OPENSYNC=libopensync1], [OPENSYNC=libopensync])
Then later in your PKG_CHECK_MODULES call, replace libopensync1 with $OPENSYNC.

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.

Resources