Library linking in C++, dependence between three libraries - c++

This might be a weird / beginners question for someone. However I have the following situation.
In my code, I am creating three libraries, lets say A,B and C. In library B i am linking library A, so something like target_link_libraries(... A).
My C library is linking against B. So I have:
B -> A
C -> B.
Should it then be possible, that I use methods, enums whatever defined in library A also in C? Although C is not linking A explicitly? I was using an enum defined in library A in C, A::someClass::someEnum and it compiled and showed correct value entries.

Should it then be possible, that I use methods, enums whatever defined in library A also in C?
Does your C library uses these methods/enums/etc. via including a header from the library A or from the library B?
If C directly includes the header from the library A, then it should be linked with the library A explicitly:
# A is a private linkage of B.
target_link_libraries(B PRIVATE A)
# C needs to be linked with A
target_link_libraries(C B A)
If C includes the header from the library B, which in turn includes the header from the library A, then A library should be a part of the B interface:
# B links with A and this linkage is an interface of B
target_link_libraries(B PUBLIC A)
# C may link with B only
target_link_libraries(C B)
These approaches assume "modern" (target-oriented) CMake to be used. But using these approaches one would get most scalable solution.

Remember that linkage dependency and compilation dependency are not the same thing.
It's quite possible that the sources of library C use definitions from headers associated with library A... irrespective of whether C depends on A when linking.
Now, in CMake, we use target_link_libraries() not only for linking. This CMake command makes sure that the library's headers are available to the dependent target, for compilation, and that its libraries are available for linking.
It's also possible for library C to require library A for linking - to have the definitions of, say, functions or variables from library A. Libraries can theoretically have circular link dependencies (which means that you need to either link against the entire circle, or no part of it).

Related

Fatal Error: Nlohmann/json.hpp not found when using cmake for Mac arm64 but works on linux [duplicate]

I am new to CMake and a bit confused with the PUBLIC, PRIVATE and INTERFACE keywords related to target_link_libraries(). Documentation mentions that they can be used to specify both the link dependencies and the link interface in one command.
What does link dependencies and link interface actually mean?
If you are creating a shared library and your source cpp files #include the headers of another library (Say, QtNetwork for example), but your header files don't include QtNetwork headers, then QtNetwork is a PRIVATE dependency.
If your source files and your headers include the headers of another library, then it is a PUBLIC dependency.
If your header files other than your source files include the headers of another library, then it is an INTERFACE dependency.
Other build properties of PUBLIC and INTERFACE dependencies are propagated to consuming libraries. http://www.cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#transitive-usage-requirements
#steveire accepted answer is great. I just wanted to add a table to quickly see the difference:
.-----------.------------------.----------------.
| | Linked by target | Link interface |
:-----------+------------------+----------------:
| PUBLIC | X | X |
:-----------+------------------+----------------:
| PRIVATE | X | |
:-----------+------------------+----------------:
| INTERFACE | | X |
'-----------'------------------'----------------'
Linked by target: libraries included in target sources (not a dependency for projects linking the library).
Link interface: libraries included in target public headers (dependencies for projects linking the library).
Not my brainchild but this extremely useful explanation helped me understand the situation. The most important part is quoted below for reference:
When A links B as PRIVATE, it is saying that A uses B in its implementation, but B is not used in any part of A's public API. Any
code that makes calls into A would not need to refer directly to
anything from B. An example of this could be a networking library A
which can be built to use one of a number of different SSL
libraries internally (which B represents). A presents a unified
interface for client code which does not reference any of the
internal SSL data structures or functions. Client code would have
no idea what SSL implementation (B) is being used by A, nor does
that client code need to care.
When A links B as INTERFACE, it is saying that A does not use B in its implementation, but B is used in A's public API. Code
that calls into A may need to refer to things from B in order to
make such calls. One example of this is an interface library which
simply forwards calls along to another library but doesn't actually
reference the objects on the way through other than by a pointer or
reference. Another example is where A is defined in CMake as an
interface library, meaning it has no actual implementation itself,
it is effectively just a collection of other libraries (I'm
probably over-simplifying here, but you get the picture).
When A links B as PUBLIC, it is essentially a combination of PRIVATE and INTERFACE. It says that A uses B in its implementation and
B is also used in A's public API.
Consider first what this means for include search paths. If something
links against A, it will also need any include search paths from B if
B is in A's public API. Thus, if A links B either as PUBLIC or
INTERFACE, then any header search paths defined for target B will also
apply to anything that links to A. Any PRIVATE header search path for
B will NOT be carried through to anything that links only to A. The
target_include_directories() command handles this. The situation with
compile flags is analogously handled with target_compile_definitions()
and target_compile_options().
Now consider the situation for the actual libraries involved. If A is
a shared library, then A will have encoded into it a dependency on B.
This information can be inspected with tools like ldd on Linux, otool
on Mac and something like Dependency Walker (a.k.a. depends.exe) on
Windows. If other code links directly to A, then it also will have
encoded into it a dependency on A. It will not, however, have a
dependency on B unless A links B either as PUBLIC or INTERFACE. So far, so
good. If, however, A is a static library, the situation changes.
Static libraries do not carry information about other libraries they
depend on. For this reason, when A links B as PRIVATE and another
target C links A, CMake will still add B to the list of libraries
to be linked for C because parts of B are needed by A, but A itself
doesn't have that dependency encoded into it. So even though B is an
internal implementation detail of A, C still needs B added to the
linker command, which CMake conveniently handles for you.
If you were paying careful attention, you would have noticed that when
A links B as PRIVATE, the include directories of B never propagate
to something linking to A, but if A is a static library, then the
linking of B behaves as though the relationship was PUBLIC. This PRIVATE-becomes-PUBLIC behaviour for static libraries only applies to
the
linking, not to the other dependencies (compiler options/flags and include search paths). The upshot of all this is that if you select
PRIVATE, PUBLIC or INTERFACE based on the explanations in the dot
points above, then CMake will ensure dependencies propagate through to
where they are required, regardless of whether libraries are static or
shared. This does, of course, rely on you the developer not missing
any dependencies or specifying the wrong PRIVATE/PUBLIC/INTERFACE
relationship.
Some answers only said when to use PRIVATE/PUBLIC/INTERFACE, but the affects are ignored. Refer:CMake-Public-Private-Interface
PUBLIC
All the objects following PUBLIC will be used for linking to the current target and providing the interface to the other targets that have dependencies on the current target.
PRIVATE
All the objects following PRIVATE will only be used for linking to the current target.
INTERFACE
All the objects following INTERFACE will only be used for providing the interface to the other targets that have dependencies on the current target.
Other posts already answered what the meaning of PUBLIC/PRIVATE/INTERFACE keywords. I want to add one more to clarify the terms "link dependencies" and "link interface."
Link dependencies :
the list of libraries to be linked by the target.
The target property LINK_LIBRARIES holds this information.
Link interface : the list of libraries to be linked by the target's dependents. The target property INTERFACE_LINK_LIBRARIES holds this information.
Probably the term "link interface" came from the old CMake wording used around LINK_INTERFACE_LIBRARIES properties, which is deprecated in favor of INTERFACE_LINK_LIBRARIES.
See the description of CMP0022, which also uses the term "link interface."
https://cmake.org/cmake/help/latest/policy/CMP0022.html
INTERFACE_LINK_LIBRARIES defines the link interface.

Is there something like maven-shade-plugin in C or C++ when linking?

I know when building Java programs, we can use maven-shade-plugin to resolve dependency confliction.
For example, if B depends on library A(version 1) and C depends on library A(version 2), both B and C can't build with the given version of library A, like the following
Though there doesn't exists one version A that satisfy both B and C, we can pacakge diffenrent versions of A into one executive. For example, we can rename library A of version 1 to A_v1, so if A.x exists in library A, it can be referred as A_v1.x. We can do the same to library A of version 2 by renaming it to A_v2.
Then, I find C/C++'s compile/link building procedure has similar aspects because it will also define and search symbols, so I am wondering if there are some ways to enable multiple version of one library be linked into one executive, by renaming tokens.
I will take the C library as an example. The function printf can be firstly renamed into version_2_12_0_printf or version_2_13_0_printf before linking, and the linker can somehow find location of the correct version of printf and link.

How to create self-contained shared library

I have a dependency problem. Library A depends on dynamic library B and C. But B depends on D ver1, while C depends on D ver2. I do not have the source for C.
How can I create a self-contained shared library containing C and D ver1, such that A can link to this new library, B, and D ver 1, and therefore avoid a conflict between D ver1 and D ver2?
You mentioned that you do not have the source of library C, but what about library A and library B? If you have those sources, update library B to depend on library D ver2 instead of library D ver1?
I would also consider merging library A and B. That would remove the dependency diamond. If you can duplicate the functionality of C, then you bring it down to a simple singular dependency on D ver2.
You can statically link your dependencies - is one option.
Or you could just stop being fixated on shipping a "self contained" library and ship your dependencies along with it. What bother is a few extra files?

On Chained static library, Do i have to add all libraries chained?

I made static library A, the library is using another static library B.
And in order to use library A in code C, i added library A and header A but B.
Because i have known that static library is combined in compile time, so library B is already contained within A.
But When i compile code C, it seem to require that i add library B also showing undefined reference error.
And when i add library B also, the error disappear.
Why ?
You'll need to add both A and B.
When static lib A uses static lib B, B is absolutely NOT combined in A. That is impossible since when generating static libraries there is no link step.
This is the difference between shared and static libraries on Linux.
If your library is written well, you may not need to add B headers in code C, but when linking, (executable or shared library or even DLL in windows) you'll need all used static libraries.

Auto linking dependencies of a static lib

I have a static lib A, which also uses static libs B, C and D.
I then have applications X and Y which both use A, but not B, C or D.
Is there some way to make it so X and Y will automatically see that A used B, C and D and link them, so that I don't need to keep track for the entire dependency tree so I can explicitly pass every static lib (quite a lot with things like Windows, Boost, etc)?
Static libraries do not link with other static libraries. Only when building the executable (or shared library/DLL) is linkage performed, and the way to keep track of this is (of course) to use make.
I think, conceptually, you might be able to merge libs together to achieve what you want - they are after simply collections of symbols ready made for the linker. Having said that, I've never seen a tool to do it. The binary format of a lib is a compiler matter, so it would have to be a mingw or gcc specific tool.
In terms of knowing which version of Boost lib A uses, there isn't really much for it but to find the documentation for A.
The easy way is to always offer the particular libraries A, B, C, and D to be linked. For a true library, the linker only retrieves the modules needed.
The key problem with A having some implicit linkage to other libraries is that they aren't necessarily uniquely identifiable. For example, should it use version 2.0 or 3.1? The one in /usr/share/lib or the one in /usr/lib/X11/xdm/share/lib? Etc.