Creating both static and shared C++ libraries - c++

I'd like to build both static and shared libraries in a project.
I know that shared libraries need to be be created from objects compiled with -fpic to get Position Independent Code while the static library doesn't need this. This is all fine and I can create either a shared or static library.
I wouldn't want to compile my source twice to get the different object files, so how is this usually done? I read how to get a shared library based on a static one. However, the example shows the static library being built with -fpic. Is this the way to go? Are there things to be aware of with this?
Is there a common approach to compiling both static and shared libraries? E.g. first static and based on the lib a shared version is created?
I'm interested to know if there are different approaches for this and what to consider when selecting.
I'm using gcc4.4 on Linux.
Thanks in advance!

The common approach that I've seen is, in fact, compiling your source twice, once with PIC and once without. If you don't do that, you either wind up with PIC overhead in the static library, or a shared object that can't be relocated by the OS (effectively meaning it's NOT shared across multiple clients of the library).

Related

Shared library with statically linked dependencies

I just wanted to understand how shared libraries with statically linked libraries are expected to perform. I am writing a shared library (lshared.so) that is statically linked to another library (lstatic). Now, I have another executable helloworld which loads a dynamic version of library lstatic (lstatic.so) and lshared.so as well. Will the static version of library (lstatic) loaded by lshared.so and the dynamic version (lstatic.so) conflict? Will they share any global state? Tried to show it better below.
helloworld
--> lshared.so (statically linked to lstatic at compile time)
--> lstatic.so (hello world loads this at runtime)
To throw some context, I've to use a shared library for logging. It is possible that lshared.so is statically linked to a different version that the one available to helloworld at runtime.
Will the static version of library (lstatic) loaded by lshared.so and the dynamic version (lstatic.so) conflict.
Possibly.
Will they share any global state.
Possibly.
The answers depend on how exactly lshared.so is built (which symbols it exports), and how the main helloworld binary is linked.
The answers also tend to be somewhat complicated, and may depend on inlining and other optimizations, and possibly on compiler versions.
It is best to avoid doing that by using shared version of lstatic.so, where all the answers become simple.

Should I link a C++ application to shared libraries which are used indirectly

Let's say you compile a C++ shared library libBeta.so which makes use of pre-existing C++ shared libraries libAlpha1.so, libAlpha2.so, libAlpha3.so, etc. If I then write a C++ application which uses libBeta.so directly (and therefore indirectly uses the other libraries), should I link my application to libBeta.so only, or should I link my application to all libraries?
My intuition tells me that I should only link to libBeta.so, because linking to all libraries seems redundant as libBeta.so is already linked to the other libraries. However, undefined reference to errors are proving my intuition wrong.
Could someone explain me why my intuition might be wrong in particular cases?
p.s.:
OS: Linux
Compiler: g++
EDIT
As it turns out the tool I was using for compiling has different behaviour for compiling an executable and compiling a shared library. Linkage to sub-libraries were being omitted when compiling a shared library :(
Shared libraries are fully linked entities, and you don't need to explicitly link to their dependencies.
This is unlike static libraries which is only a collection of object files. When you use a static library you must link to its dependencies. But for share libraries, no you don't need that.
If you get undefined references, then it's not for the dependencies of the shared libraries you link to. It's either that you are missing linking with your own code, or you actually link with a static library.
You only need to link with your direct dependency, libBeta.so.
Actually, a few years ago on some Linux distributions you could get away with having indirect dependencies in your executable -- in this case, say, on libAlpha1.so -- and as long as the dependency gets loaded at runtime, directly or indirectly, the dependency would get satisfied.
This is no longer the case.

Relations between executables, static libraries and shared libraries

I am writing a build system for a project and I am not sure about the links between executables, static libraries and shared libraries.
For me there are three affirmations:
An executable can use both static and shared libraries.
A static library can use both static and shared libraries.
A shared library can only use static libraries.
I have still doubts about the third affirmation...
Can you enlighten me on this?
To use a static library's basically like linking a .o or .obj file: all the implementation's linked into the using application or library at that specific point in time. Changes made to the static library after that time won't be picked up automatically by the code that linked it... the latter would need to be relinked for the changes to be incorporated.
Shared libraries defer the linking until runtime, which means every time the code using a shared library invokes some functionality within it, the version of the shared library which is found at runtime is utilised. As long as the changes don't affect the public API, you can replace a shared library and applications that find it at runtime will pick up the updates/changes without themselves having to be modified/relinked.
So, yes an executable can use both, a static library can use both, and your third "affirmation" is wrong: a shared library can also use both. It just means the shared library itself may use a snapshot of functionality from a static library, or it may find other functionality from another shared library at runtime.

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.

static library, but I still need headers?

I have a bunch of projects that all could share a "common" static library of classes.
What confuses me is if I make a static library out of these classes and link against it in my projects that I still need the headers of the classes in the static library in my main projects.
What is the benefit of the static library then?
How do companies like Adobe deal with this?
Static libraries allow you to create a library and use that library in many projects.
The need for header files:
Since the project using the library is programmed and compiled independent of the library, that program needs to know the declaration of the things you're using. Otherwise how would your compiler know you're writing valid code?
A compiler only takes source code as input and produces output. It does not deal with compiled object files or static libraries on input.
The need for linking in the library:
So having the headers allows you to write valid code in your project, but when it comes to link time you'll need to provide the definition which is contained inside the static library.
The linker takes all object files (compiled code) and also all static libraries and produces an executable or binary.
More info about static libraries (benefits, comparing dynamic, etc...):
Amongst other things, it is nice to separate your project into libraries so that you don't end up with 1 huge monolithic project.
You do not need to distribute the source code (typically in the .cpp files) this way.
If you were to simply include all the .cpp files in every project that used the common library then you would have to compile the .cpp files each time.
An advantage of static libraries over dynamic libraries is that you can always be sure that your programs will be self contained and that they are using the correct version of the library (since they are compiled into the executable itself). You will also have a slight speed advantage over dynamic linking.
Disadvantages of static libraries over dynamic libraries include that your file sizes will be bigger because each executable needs their own copy, and that you can't swap out a different version of the library since it's not dynamically loaded.
Re your question: How do companies deal with this:
A typical company will make use of both static and dynamic libraries extensively.
The typical way you make use of a static library is to have a target in your Makefile (or whatever build system you use) that installs the headers into an appropriate location at the same time that it installs the library.
So, your static library ends up in /usr/local/lib, and the headers go into /usr/local/include or wherever.
Also, when compared with linking against object files, linking against static library may result is a smaller final executable. The reason for this is, if you don't call any of the functions from a particular object file (included in the static library), the linker will not include the code for those functions in you final executable. See Extraneous Library Linkage