Checking library version of shared library (so-file) in autoconf - c

Libraries typically have a package/release version as well as a library version. These have very different semantics.
Is there a standard way to check the availability of a library with a given library version using Autoconf, i.e., a macro in configure.ac?
Things that can be done, but are bad in my opinion (correct me if I am wrong):
Rely on the name of the postfix of the so-file. Weak verification.
Add artificial function in each version of the library and check for this in the standard Autoconf way. Ugly and assumes that I build the library.
Embed the lib version in the header file, check that this matches with grep-ish tricks, and assume that this matches the version in the lib. Risk of mismatch between header file and library and assumes I build the library.
What I want is a solution that inspects the actual library version
embedded in the library itself. I feel stupid, but I have googled
quite a lot and do not find anything.

Related

How should dynamic, system-level libraries be bundled into a Rust crate?

When creating a wrapper around a (C) library libfoo that is either itself commonly dynamically linked or links some dependencies dynamically, should the crate libfoo-sys include this library and its dependencies in some way? If so, how?
In case libfoo-sys should not include the library, how should the crate ensure a sufficiently compatible version is present on the system?
The most pragmatic thing I can think of is for the build of dependents to fail if the relevant libfoo version is missing. An alternative would be to try to install the relevant version with common package managers instead but I'd be worried to break a crate-user's environment in that way.
I looked at some examples of wrapper crates and couldn't find any indication of them including the base library which seems odd to me. Searching for the question didn't yield any definitive answer.
Edit: I am most interested in the case of libfoo not supporting static linking at all, or very badly.

Can I use one Linux .so for all Linux compilers?

We need to integrate a closed-source C library into our project. The other party can compile the library in any mode we need, but we support a lot of different Windows and Linux compilers.
I know a DLL will be compatible with all major Windows compilers, so we could only use one library for Windows. But I’m not familiar with Linux dynamic libraries (.so). Are these compatible across all Linux environments in a similar way?
Thanks
You may have some issues w.r.t. the version of the GNU libc against which that shared library libotherparty.so has been linked (and compiled).
You certainly need to know the version of the libc, and you might require that party to ship several variants of the binary library.
I would strongly suggest to read Drepper's paper: How To Write Shared Libraries. See also this question and Levine's linker & loader book.
If it is C code, the compiler does not matter much. What matters more is the ABI. Learn also about symbol versioning.
Be prepared to have some trouble.
You'll learn by experience that free software is preferable.
Library versions should be specified for shared objects if the function interfaces are expected to change (C++ public/protected class definitions), more or fewer functions are included in the library, the function prototype changes (return data type (int, const int, ...) or argument list changes) or data type changes (object definitions: class data members, inheritance, virtual functions, ...).
The library version can be specified when the shared object library is created. If the library is expected to be updated, then a library version should be specified. This is especially important for shared object libraries which are dynamically linked. This also avoids the Microsoft "DLL hell" problem of conflicting libraries where a system upgrade which changes a standard library breaks an older application expecting an older version of the the shared object function.
Versioning occurs with the GNU C/C++ libraries as well. This often make binaries compiled with one version of the GNU tools incompatible with binaries compiled with other versions unless those versions also reside on the system. Multiple versions of the same library can reside on the same system due to versioning. The version of the library is included in the symbol name so the linker knows which version to link with.
One can look at the symbol version used: nm csub1.o
00000000 T ctest1
No version is specified in object code by default.
Look ld and object file layout
There is one GNU C/C++ compiler flag that explicitly deals with symbol versioning. Specify the version script to use at compile time with the flag: --version-script=your-version-script-file
Note: This is only useful when creating shared libraries. It is assumed that the programmer knows which libraries to link with when static linking. Runtime linking allows opportunity for library incompatibility.
Also look here regarding ABI compatibility

Linking to SSL shared library of different versions

My app uses only functions supported in OpenSSL 0.9.8 and later, but I compile it on a system with a 1.0.0 library installed (with -lcrypto), and the app requires libcrypto.so.1.0.0 or later at install time.
OpenSSL apparently compiles the entire version level "libcrypto.so.1.0.0" into the SONAME of the library, so my app won't run unless this specific version of the library exists. I get that it won't run on a system with only 0.9.8 installed, but what if 1.0.1 is installed?
For every other shared library I use (-lpthreads, -lncurses, ..), ldd shows the SONAME as "libxxx.so.N", so I only need version N installed. OpenSSL is the only library I'm aware of that depends on a very specific version level (V.R.M), so I worry that the app won't run if the installed library is later than libcrypto.so.1.0.0 (or the library is updated to a more recent level).
Is there a way to compile my app to use "libcrypto.so or "libcrypto.so.1" regardless of what version it's linked to? And why does OpenSSL use the full version in the SONAME when no other library I'm aware of does this?
No, there is no reliable way because in OpenSSL the internal structures keep changing between versions, and quite a few functions are actually macros which access/manipulate the structure members directly.
Still if you are SURE your application does not use any such macros and willing to take the risk the structures may change and your app won't work, you can dlopen() the libcrypto.so and dlsym() the functions you use. There would be around 20 of them. Keep in mind that many functions you may be using, such as SSL_CTX_set_options and SSL_want_read/SSL_want_write are actually macros which result in calling the same functions.
Another option would be to link statically with libcrypto.a and libssl.a. This would also make your app to run on systems which do not have OpenSSL installed at all (although those are few). Expect this to add 300-900kb to the size of your app though.

Hiding a library within a library

Here's the situation. I have an old legacy library that is broken in many places, but has a lot of important code built in (we do not have the source, just the lib + headers). The functions exposed by this library have to be handled in a "special" way, some post and pre-processing or things go bad. What I'm thinking is to create another library that uses this old library, and exposes a new set of functions that are "safe".
I quickly tried creating this new library, and linked that into the main program. However, it still links to the symbols in the old library that are exposed through the new library.
One thing would obviously be to ask people not to use these functions, but if I could hide them through some way, only exposing the safe functions, that would be even better.
Is it possible? Alternatives?
(it's running on an ARM microcontroller. the file format is ELF, and the OS is an RTOS from Keil, using their compiler)
[update]
Here's what i ended up doing: I created dummy functions within the new library that use the same prototypes as the ones in the old. Linked the new library into the main program, and if the other developers try to use the "bad" functions from the old library it will break the build with a "Symbol abcd multiply defined (by old_lib.o and new_lib.o)." Good enough for government work...
[update2]
I actually found out that i can manually hide components of a library when linking them in through the IDE =P, much better solution. sorry for taking up space here.
If you're using the GNU binutils, objcopy can prefix all symbols with a string of your choice. Just use objcopy --prefix-symbols=brokenlib_ old.so new.so (be careful: omitting new.so will cause old.so to be overwritten!)
Now you use brokenlib_foo() to call the original version of foo().
If you use libtool to compile and link the library instead of ld, you can provide -export-symbols to control the output symbols, but this will only work if your old library can be statically linked. If it is dynamically linked (.so, .dylib, or .dll), this will not be possible.

Including third-party libraries in C applications

I'm a bit naive when it comes to application development in C. I've been writing a lot of code for a programming language I'm working on and I want to include stuff from ICU (for internationalization and unicode support).
The problem is, I'm just not sure if there are any conventions for including a third party library. for something like readline where lots of systems are probably going to have it installed already, it's safe to just link to it (I think). But what about if I wanted to include a version of the library in my own code? Is this common or am I thinking about this all wrong?
If your code requires 3rd party libraries, you need to check for them before you build. On Linux, at least with open-source, the canonical way to do this is to use Autotools to write a configure script that looks for both the presence of libraries and how to use them. Thankfully this is pretty automated and there are tons of examples. Basically you write a configure.ac (and/or a Makefile.am) which are the source files for autoconf and automake respectively. They're transformed into configure and Makefile.in, and ./configure conditionally builds the Makefile with any configure-time options you specify.
Note that this is really only for Linux. I guess the canonical way to do it on Windows is with a project file for an IDE...
If it is a .lib and it has no runtime linked libraries it gets complied into you code. If you need to link to dynamic libraries you will have to assure they are there provide a installer or point the user to where they can obtain them.
If you are talking about shipping your software off to end users and are worried about dependencies - you have to provide them correct packages/installers that include the dependencies needed to run your software, or otherwise make sure the user can get them (subject to local laws, export laws, etc, etc, etc, but that's all about licensing).
You could build your software and statically link in ICU and whatever else you use, or you can ship your software and the ICU shared libraries.
It depends on the OS you're targeting. For Linux and Unix system, you will typically see dynamic linking, so the application will use the library that is already installed on the system. If you do this, that means it's up to the user to obtain the library if they don't already have it. Package managers in Linux will do this for you if you package your application in the distro's package format.
On Windows you typically see static linking, which means the application bundles the library and it will use that specific version. many different applications may use the same library but include their own version. So you can have many copies of the library floating around on your system.
The problem with shipping a copy of the library with your code is that you don't get the benefit of the library's maintainers' bug fixes for free. Obscure, small, and unsupported libraries are generally worth linking statically. Otherwise I'd just add the dependency and ensure that whatever packages you ship indicate it appropriately.

Resources