Relations between executables, static libraries and shared libraries - c++

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.

Related

C++: Linking an external library to a dll library

I'm currently developing a shared library on Windows (dll) with c++.
The library depends on another external library.
What is the best way to link them together?
Link the external library as a static library into my shared lib?
Link it as a shared library and provide the dll to the application who is using my shared lib?
For the second case what happens if i create an application which uses my own created shared library and also the external library as a shared library?
If for example my shared library is build with the external library version 1.1 and the application uses the newer Version for example 1.3 ? Now the dlls should be different but how could i provide them to the main application?
Are there some best practices or recommendations on how to handle such a situation?
This really depends on what you want to do and how you are deploying your library.
shared/dynamic libraries (dll's on windows) have several advantages over static libraries
They can be distributed externally from the application, allowing your application binary to be smaller
They can be updated externally to the application
They are slightly more efficient as code is only executed if its needed rather than being bundled with the executable
Of course they have several weaknesses too
They can be distributed externally from your application and updated externally - allowing dll injection attacks
Trying to release dynamic libraries with the executable is one of the most painful and horrible things to do (especially on windows where there is no RPATH)
You may have to use a dll, dependent on your external libraries licensing, Qt for example requires shared library linking in many cases (not all).
Standard convention is usually to offer shared and static versions of your library with the shared version being completely linked to other shared libraries and the static version being an ar static library (includes all dependencies). The shared library variant then offers instructions on linking (i.e a .pc (pkgconfig) file) which specifies the versions of the other libraries to link to (i.e v1.1 of x.dll) in order to successfully compile/link.

cmake build a shared library that contains all its dependencies

I have built a shared library that depends on a bunch of other libraries. But when loading that shared library, it needs the dependent libraries to be present in order to run properly. I want this shared library to be portable and hence want it to contain all the dependencies in itself. Is there a way in cmake to do this or what is the best solution here?
Actually this is not related with CMake, but with concepts of linking. You should link with static version of all your dependent libraries.

Do shared libraries (.so) files need to present (or specified) at link time?

Do shared libraries (.so) files need to present (or specified) at link time?
I've read here (Difference between shared objects (.so), static libraries (.a), and DLL's (.so)?) that .so files must be present at compile time, but in my experience this is not true?
Doesn't shared libraries just get linked at runtime using dlopen and dlsym, so that the library may not be present on the system, when the application is linked?
Most shared libraries need to be present both at build time and at run time. Notice that shared libraries are not DLLs (which is a Windows thing).
I assume you code for Linux. Details are different on other OSes (and they matter).
For example, if you are compiling a Qt application, you need the Qt shared libraries (such as /usr/lib/x86_64-linux-gnu/libQt5Gui.so and many others) both when building your application and when running it. Read about the dynamic linker ld-linux.so(8) & about ELF.
But you are asking about dynamic loading (using dlopen(3) with dlsym(3) ...) of plugins.
Then read Levine's Linkers & Loaders, Program Library HowTo, C++ dlopen mini HowTo, and Drepper's How To Write Shared Libraries
See also this answer.
Some libraries and frameworks try to abstract the loading of plugins in an OS-neutral manner. Read e.g. about Qt plugins support, or about POCO shared libraries (poorly named, it is about plugins).
You can have it both way, it all works.
While with library present at compile time,instead of get library by dlopen/LoadLibrary explictly, you can use all the functions directly

Static, Shared and executable - Windows and Linux

I have certain doubts:
Use case:
A static library containing a global variable, static variable, a function
and a class defined
A shared library uses these and hence they are part of the same.
A executable program also uses the same and they are part of the same.
The executable loads the shared library on run time
What all differs between windows and Linux?
Can the shared library use something from executable's static library objects?
Can the executable use something from shared library's static library objects?
What is the role of loader? For ex: does the static library objects in static library are shared between shared library and executable on Linux?
Is there any difference if the shared libraryis loaded at runtime or load time?
In the library that you define your global static you can define it as follows:
static int g_i=9;
when accessing g_i from other modules then you should use extern to tell the compiler that g_i is defined in another module:
extern int g_i;
This is all Standard C and there should be no differences between the different C compilers regardless of operating systems.
A library can't reference anything in the executable since that would cause a circular reference, rather you should take the shared functionality in the executable and add it to a third library that is referenced by both the existing library and the executable.
There are different use cases where you rather want dynamic loading over static linking. Static libraries makes your executables larger, while dynamic libraries can cause "DLL Hell". Mostly people use shared libraries when they want to share the code between different programs and use static libraries when they only are going to use the library in only one program.

Creating both static and shared C++ libraries

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