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.
Related
I try to develop a thirdparty unixODBC driver, it is a secondary development based on the original file libodbc.so.2.0.0.
so I want to rename 'libodbc.so.2.0.0' to 'libodbc.so.2.0.0_renamed'. And soft link my dynamic library file to libodbc.so.2.0.0.
But I found an issue bothering me, when I rename native file and run 'sudo ldconfig', the file named 'libodbc.so.2' automatically linked to the renamed file 'libodbc.so.2.0.0_renamed', as below:
I could not understand that:
why it occurs;
how to appropriately replace the library.
I don't have enough ackownledge about linux, so that I failed to get any keyword to search and deal with it.
Could you help me, thank you very much!
Shared objects under GNU/Linux follow a specific version naming scheme, which is known by the loader (and OS component, actually part of libc framework) to determine if a newer library is retro-compatible with some older version to which a binary was originally linked against. By adding the renamed suffix, you are violating the convention and the dynamic linking system is getting confused. You should renamed as suggested by #Bodo above.
In addition, perhaps rather than using rename, you might consider using the very versioning scheme. From GNU Build System (aka Autotools) manual, the version cheme is like it follows:
Versioning: CURRENT:REVISION:AGE
CURRENT The latest interface implemented.
REVISION The implementation number of CURRENT (read: number of bugs fixed...)
AGE The number of interfaces implemented, minus one.
The library supports all interfaces between CURRENT − AGE and CURRENT.
If you have
not changed the interface (bug fixes) CURRENT : REVISION+1 : AGE
augmented the interface (new functions) CURRENT+1 : 0 : AGE+1
broken old interface (e.g. removed functions) CURRENT+1 : 0 : 0
Therefore a possible history of your lib might be:
1:0:0 start
1:1:0 bug fix
1:2:0 bug fix
2:0:1 new function
2:1:1 bug fix
2:2:1 bug fix
3:0:0 broke api
3:1:0 bug fix
4:1:1 bug fix
5:0:0 broke api
You might, for instance, call the older and newer versions of libodbc.so.x.y.z, according to your needs. Just an idea.
I've written a Tcl script that uses the TclMagick extension together with GraphicsMagick.
For GraphicsMagick, I've both the Windows DLLs and the Linux SO files. I want to be able to make two Starkit/Starpack applications bundled with those libraries: one for Windows (with the DLLs) and one for Linux (with the SO files).
Is this reasonable? Can it be done?
EDIT
I cannot seem to use DLLs with dependencies under Windows. In my case, I want to use the TclMagick extension, but it needs the GraphicsMagick's DLLs and the starkit cannot find those. What should I do in this situation?
Yes. In the lib/tclmagick subdirectory of $starkit::topdir, you'll place the dynamic library and an appropriate pkgIndex.tcl file that loads the library. Use a Makefile or some other build script to use the correct dynamic library file, and generate the pkgIndex, depending the target platform.
The directory hierarchy:
appname.vfs/
main.tcl
lib/
app-appname/
appname.tcl
pkgIndex.tcl
tclmagick/
pkgIndex.tcl
tclMagick.so
package require tclmagick will work as you expect, for some capitalization of "tclmagick"
You can do it, but you might need some extra windows trickery to get things to work properly.
Windows has quite a few options to load dependent libraries, this page explains the basics:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
There are is one part that can help you:
If a DLL with the same module name is already loaded in memory, the system checks only for redirection and a manifest before resolving to the loaded DLL, no matter which directory it is in. The system does not search for the DLL.
So, to get the dependencies right, you could get the dependent libraries loaded into memory first (sadly you cannot use load for this, but could use something from twapi, e.g. twapi::load_libary (see http://wiki.tcl.tk/9886) to get the library loaded from some temporary location).
Sadly most OS's do not provide an easy or portable way to load a dynamic library directly from memory, so you need to copy the dependent libs to a temporary location first (you can do it with appropriate hacks or by using something like an installable filesystem on windows/FUSE on Linux).
In most cases the easiest route is to just link all dependencies statically into the extension instead.
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.
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.
Im using a market data source implementation that contains .so.0 files. However these are 'soft links' to actual .so.0.0.0 files. Why is this done?
When I try to copy these .so.0 links, it ends up copying an exact replica of the .so.0.0.0 file but with a .so.0 prefix.
Added comment:
so I have a libfoo.so file, and it is being accessed by java through jni. This libfoo.so file is actually a soft link that points to libfoo.so.0.0.0 What happens if I don't have libfoo.so. How does java/or any other compiled code, figure out that libfoo.so.0.0.0 if the shared object to use?
This is so programs can bind to either any version of libfoo that has the same interface (I want the latest updates to libfoo), or bind to a specific version (I want stability and only the exact version I tested against).
The .0 and .0.0.0 files exist so that versioning can happen:
foo.0 represents the .0 version of a library. All .0 versions of the library will use the same interface, but there may be different implementations. (Hopefully, the later implementations will have fewer bugs than the earlier ones.)
foo.0.0.0 represents a specific implementation of the .0 version.
It's not useful, now, to have the soft-link. But here's what could happen:
The programmer of foo finds a bug in his library. He releases foo.0.0.1. And foo.0 now links to foo.0.0.1. Then two things happen:
All files that link to foo.0 will automatically update to foo.0.0.1.
All files that link to foo.0.0.0 will continue to use the old foo.0.0.0