What's the common way to manage shared libraries on Linux? - c++

For example, I need to generate a shared library, libXXX.so.
What's the common way to generate it? Only use -fPIC -shared ?
Do I need to create a soft link to this library? I mean using ln -s.
What if I update the shared libray, ie. from libXXX.so.1.2.3 to libXXX.so.1.2.4, how my project knows that the shared library is updated? Do I need to re-compile the whole project again?
What's the common way to manage the shared library in Makefile?
I totally do not understand these issues. Please do me a favor :-)

The topic on which you have raised the question is vast. Most of your questions depend upon your environment and also whether or not to create a softlink depends on in which folder you keep your library and which processes may need to access it etc.
Please check this link & this link also which gives a detailed explanation on creating and using shared libraries.
Some short answers to your questions:
What's the common way to generate it? Only use -fPIC -shared ?
The options used depends on the compiler. fPIC helps in generating position independent code and shared makes the library a shared library. But, apart from, there are also options which can expose only those symbols which you decide to export from your library and options which create a strong link between the global symbols of your library (-symbolic) etc.
Do I need to create a soft link to this library? I mean using ln -s.
As I mentioned above, this depends on where you decide to place your library. The common mechanism is keep your library in some folder of your choice and create a link to it in commonly "known" or accessible folder like /usr/lib etc.
What if I update the shared libray, ie. from libXXX.so.1.2.3 to
libXXX.so.1.2.4, how my project knows that the shared library is
updated? Do I need to re-compile the whole project again?
One of the main advantages of shared library is that you can update latest versions without having to recompile the entire code. Again achieving this depends on the platform & compiler.
What's the common way to manage the shared library in Makefile?
There are umpteen links available in google and my link also provides some basic detail.

Related

Search order in LD_LIBRARY_PATH

A shared object library required by my program is present in two paths under LD_LIBRARY_PATH, but only one of the two should be loaded by my program because of version compatibility issue. For example, if LD_LIBRARY_PATH is path1:path2 and the shared library libxxx.so is in both path1 and path2, will path1/libxxx.so be loaded or path2/libxxx.so be loaded when I run the program?
Also I would appreciate it if anyone has a better solution than reordering the paths in LD_LIBRARY_PATH. After searching on the internet I saw some solution using rpath but didn't quite understand how that works.
The directories get searched in the order they appear in LD_LIBRARY_PATH.
Keep in mind that the loader also looks elsewhere, not just LD_LIBRARY_PATH, which may or may not be a factor.
Since you asked for a "better solution", here are two:
Get this broken shared library built correctly
There is a well-established mechanism and convention for versioning shared libraries so that different versions of the same shared library get loaded. A program that needs a particular version of a shared library will load the one that it needs.
In fact, it's a safe bet that you already have a bunch of different versions of multiple shared libraries installed, due to applications in your Linux distribution that need different versions of the same shared library.
This is nothing more complicated than not using the same name for incompatible versions of the same shared library. There is a well-defined convention for naming actual shared library filenames, that work together with the linker in order to make this happen (the -soname link option, see your linker documentation for more information).
Don't use LD_LIBRARY_PATH
It is possible to link an executable and embed in the executable itself a pathname to search, first and foremost, for any shared libraries, either before or after LD_LIBRARY_PATH.
Remove all directories from LD_LIBRARY_PATH.
Use the -rpath, with/without --enable-new-dtags or --disable-new-dtags option when linking your executable. The correct set of options depends on your specific details, and specific versions of your linker. See your linker documentation for more information. You mentioned you tried to find information on this in Google, but all that Google will do is, perhaps, refer you to the same documentation that you already have: the manual pages for the linker. That's the best source for complete information on using this or any other linker option.
The best solution depends on your specific circumstances; whether you're building the executable, and/or shared libraries, how easy/hard it is to change whatever you're building; or whether you're not building anything at all, just black boxes that need to be executed.

How do I create a static library which automatically links to a dynamic library?

I maintain our in-house infrastructure library - lets call it libcluracan. This library has to be statically linked because it doesn't exist on outside computers where the code is used.
This means that instead of creating a libcluracan.so file using the linker I create a libcluracan.a file using the ar command
Now I'm trying to add some new functionality to libcluracan, but it requires linking with an outside library - specifically -lfltk, but the specifics aren't important. What is important is that I can assume the outside computers have this library (and any other publicly available library I need).
The biggest problem is that I can't change how the in-house programmers compile (well, link) their code.
Had we been using a dynamic libcluracan.so library I'd just add -lfltk to the linker and forget about it - the programmers would continue to link with -lcluracan and get -lfltk automatically.
I need to find a way to do the same thing with our static libcluracan.a library.
TL;DR
Is there a way to create a static .a library that automatically links to another dynamic .so library when used?
The biggest problem is that I can't change how the in-house programmers compile (well, link) their code.
That is indeed a big problem. Your in-house programmers should be using make (or a similar automated build system), and the change would be trivial.
There is no way to achieve what you want on an arbitrary UNIX system.
IF you are using GNU toolchain, and in particular GNU-ld or gold, THEN you can achieve what you want by linking with libcluracan.so, where libcluracan.so is not a shared library, but a linker script, which looks like this:
GROUP ( libcluracan.a libfltk.so )

libgomp.so.1: cannot open shared object file

I am using OpenMP in my C++ code.
The libgomp.so.1 exists in my lib folder. I also added its path to the LD_LIBRARY_PATH
Still at run-time I get the error message: libgomp.so.1: cannot open shared object file
At Compile time I compile my code with -fopenmp option.
Any idea what can cause the problem?
Thanks
Use static linking for your program. In your case, that means using -fopenmp -static, and if necessary specifying the full paths to the relevant librt.a and libgomp.a libraries.
This solves your problem as static linking just packages all code necessary to run you program together with your binary. Therefore, your target system does not need to look up any dynamic libraries, it doesn't even matter if they are present on the target system.
Note that static linking is not a miracle cure. For your particular problem with the weird hardware emulator, it should be a good approach. In general, however, there are (at least) two downsides to static linking:
binary size. Imagine if you linked all your KDE programs statically, so you would essentially have hundreds of copies of all the KDE/QT libs on your system when you could have just one if you used shared libraries
update paths. Suppose that people find a security problem in a library x. With shared libraries, it's enough if you simply update the library once a patch is available. If all your applications were statically linked, you would have to wait for all of these developers to re-link and re-release their applications.

Building a new library on top of another library (SDL and Eclipse)

I am working on a project with SDL. I feel like a lot of my code could/should be reusable for any other projects I might want to take on.
I was going to start a library project, but I don't know how to go about linking to the SDL libraries.
Usually, I go to Project Settings and edited Mingw32 Linker to include the libraries (ming32, SDLmain, and SDL). But the linker does not show up in the settings.
So my questions:
Is there no linker settings because building a library is only a compiling operation?
And in general, is it possible to build a library on top of the existing libraries? That is, write my library using SDL functions and stucts. Or would I have to get the source code and rebuild entirely with my code included?
Also, advice on shared vs. static in this instance?
(Also, any advice for where to go about learning more about compilers and linkers and such. I got through data structures in school but no farther)
As an introduction, you have to distinguish very well static library from dynamic ones, they are completely different beasts... said that, to your questions:
Is there no linker settings because building a library is only a compiling operation?
I guess you are creating a static library in this case. A static library is simply the collection in one single object file of all the individual object files (i.e., the .o files produced by the compiler) that make up your source tree. No more, no less.
With a static library you don't need to specify which are the dependencies, since it is understood that it is when compiling the final executable that your library will be linked with all the other libraries that it depends upon. Therefore it is only at that time (final executable build) that any missing symbol will be detected, and all other libraries must be available.
A shared library (also dynamic library), is an executable file that embeds all the static libraries that it depends upon. It can also have external dependencies with other shared library, which would not be embedded.
And in general, is it possible to build a library on top of the existing libraries? That is, write my library using SDL functions and stucts. Or would I have to get the source code and rebuild entirely with my code included?
It is perfectly possible, both for static and dynamic libraries.
Also, advice on shared vs. static in this instance?
In this instance it is not possible to advice, because you don't specify enough information.
Look at this: When to use dynamic vs. static libraries, and this, to have a sort of guideline.
(Also, any advice for where to go about learning more about compilers and linkers and such. I got through data structures in school but no farther)
I think that the two links above give you plenty of information. If you want to further go into details, you could start from this wikipedia article and browse from there.
The library you are building can have external dependencies. That means that you can link it with SDL or any other external libraries that you like.
I think this page explains all your other questions: DLL Creation in MingW

Should I create .a or .so when packaging my code as a library?

I have a software library and I used to create .a files, so that people can install them and link against them: g++ foo.o -L/path/to -llibrary
But now I often encounter third-party libraries where only .so files are available (instead of .a), and you just link against them without the -l switch, e.g. g++ foo.o /path/to/liblibrary.so.
What are the differences between these solutions? Should I prefer creating .so files for the users of my library?
Typically, libfoo.a is a static library, and libfoo.so is a shared library. You can use the same -L/-l linker options against either a static or shared. Or you can name the full path to the lib with static or shared. Often libraries are built both static and shared to provide application developers the choice of which they want.
All the code needed from a static lib is part of the final executable. This obviously makes it bigger, but it also means it's self-contained. Once it is compiled, you can run your app without the lib.
Code from a shared lib is not part of the executable. There are just some hooks in place to make the executable aware of the name of the lib it needs. In order to run your app, the shared lib has to be present in the lib search path (e.g. $LD_LIBRARY_PATH).
If you have two apps that share the same code, they can each link against a shared lib to keep the binary size down. If you want to upgrade parts of the app without rebuilding the whole thing, shared libs are good for that too.
Good overview of static, shared dynamic and loadable libraries at
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
Some features that aren't really called out from comments I've seen so far.
Static linkage (.a/.lib)
Sharing memory between these compilation units is generally ok because they should(?will) all be using the same runtime.
Static linkage means you avoid 'dll hell' but the cost is recompilation to make use of any change at all. static linkage into Shared libraries (.so) can lead to strange results if you have more than 1 such shared library used by the final executable - global variables may exist multiple times and which one is used and when they are initialised can cause an entirely different hell.
The library will be part of the shipped product but obfuscated and not directly usable.
Shared/Dynamic libraries (.so/.dll)
Sharing memory between these compilation units can be hazardous as they may choose to use different runtime. This can mean you provide different Shared/Dynamic libraries based on the debug/release or single/multi threaded or...
Shared libraries (.so) are less prone to 'dll hell' then Dynamic libraries (.dll) as they include options for quite specific versioning.
Compiling against a .so will capture version information internal to the file (hard to fake) so that you get quite specific .so usage. Compiling against the .lib/.dll only gives a basic file name, any versioning is done managed by the developer (using naming or manually loading the library and checking version details by hand)
The library will have to ship with the final product (somebody else can pick it up and use it)
But now I often encounter third-party libraries where only .so files are available [...] and you just link against them without the -l switch, e.g. g++ foo.o /path/to/liblibrary.so.
JFYI, if you link to a shared library which does not have a SONAME set (compare with readelf -a liblibrary.so), you will end up putting the specified path of liblibrary.so into your target object (executable or another shared library), and which is usually undesired, for users have their own ideas of where to put a program and its associated files. The preferred way is to use -L/path/to -llibrary, perhaps together with -Wl,-rpath,/whatever/path/to if this is the final path (such pathing decisions are made by Linux distributions for example).
Should I prefer creating .so files for the users of my library?
If you distribute source code, the user will make the particular choice.