CMake target_link_libraries Interface Dependencies - cmake

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.

Related

How can I make `target_link_libraries` dependencies transitive from OBJECT libraries in cmake?

If I specify a dependency chain of OBJECT libraries in CMake, only the target_link_libraries dependencies of the very last one is used in the target executable.
Minimal Example:
main depends on objB, which depends on objA.
Both objA and objB are OBJECT libraries in CMake.
I would expect main to link with both object files. It doesn't.
cmake_minimum_required(VERSION 3.13)
project(transitive-object-library-link-issue VERSION 1.0.0 LANGUAGES C)
add_library(objA OBJECT a.c)
add_library(objB OBJECT b.c)
target_link_libraries(objB PUBLIC objA)
# Should link with 'a.o', since 'objA' is "linked" by 'objB'
add_executable(main main.c)
target_link_libraries(main objB)
Note: A working set of files are available at https://github.com/scraimer/cmake-transitive-object-library-link-issue
If I change objA to a non-OBJECT library, the problem is eliminated by getting rid of the chain of OBJECT library dependencies. In other words, change the line
add_library(objA OBJECT a.c)
To be:
add_library(objA a.c)
So it's something specific to OBJECT libraries. How should I be specifying the dependencies to make main link with objA? (Without having to specify objA in every executable target that uses objB)
Object library targets are not real libraries, they are simply a collection of objects, but they are not really linked together until they are used to build a real target like an executable or shared/static library. Citing the linked documentation:
add_library(<name> OBJECT <src>...)
Creates an Object Library. An object library compiles source files but does not archive or link their object files into a library.
In despite of that, you can apply a target_link_library() command to an object library, but only to specify dependencies of their sources on other libraries. The linked documentation explains your problem:
The object library’s usage requirements are propagated transitively [...], but its object files are not.
Object Libraries may “link” to other object libraries to get usage requirements, but since they do not have a link step nothing is done with their object files.
So, the transitive propagation affects only to compile definitions and dependencies of other real libraries, not the objects themselves.
One solution is to define an INTERFACE library for each OBJECT library. Dependencies of interface libraries are transitive.
# Defines an object library named ${T}_obj,
# interface library named ${T} linked to it,
# and sets ${varname} to ${T}_obj.
macro(add_object varname T)
add_library(${T}_obj OBJECT ${ARGN})
add_library(${T} INTERFACE)
target_link_libraries(${T} INTERFACE ${T}_obj $<TARGET_OBJECTS:${T}_obj>)
set(${varname} ${T}_obj)
endmacro(add_object)
Usage
add_object(T a a.c)
add_object(T b b.c) # sets T to b_obj
target_link_libraries(${T} a)
This stems from another issue with OBJECT libraries: duplication of object code. As Brad King explains:
we'd need to be careful to de-duplicate use of [example item's] object files
If transitive propagation was the default, you could accidentally cause the linker to try linking multiple copies of the same code, thus dooming your project to be non-compilable by CMake.
That is a good enough reason not to allow transitive dependencies of OBJECT libraries. It's tricky, so best avoided. So much so that it's mentioned as a Good Practice in his excellent book "Professional CMake: A Practical Guide":
If a target uses something from a library, it should always link directly to that library. Even if the
library is already a link dependency of something else the target links to, do not rely on an indirect
link dependency for something a target uses directly.
He also added in another issue:
he transitive nature of object libraries is not the same as regular libraries. The build-system manual words it like this:
The link (or archiving) step of those other targets will use the object files from object libraries that are directly linked.
The key part of that is the "directly linked". In your example, main gets the objects from b because it links directly to b, but because it does not link directly to a, it does not get a's objects, even though b links to a.
The reason for this is related to problems where deep transivity can result in object files being added multiple times, which will cause an error. This particular aspect has come up a few times in the issue tracker, but I don't have the issue numbers at hand (you can probably search for them and track down the various discussions).
So the solution seems to be to avoid relying on target_link_library for OBJECT libraries. There are two ways: First is to simply not use OBJECT libraries. Second is to explicitly specify objects to link in the hierarchy, as proposed by Hiroshi Miura:
add_library(a OBJECT a.c)
add_library(b OBJECT b.c)
target_sources(b PUBLIC $<TARGET_OBJECTS:a>)
add_executable(main main.c)
target_sources(main PRIVATE $<TARGET_OBJECTS:b>)
This is explicit, but doesn't even solve the problem I have! I suspect this also might run into duplication issues due to diamond patterns, but I haven't tested that.
Maybe over the next few months I'll figure out a better solution using generator expressions based on the LINK_LIBRARIES property of the objA. Not sure how to do that, though.

How to create a wrapper library without exposing the underlying library being used?

Using Cmake I would like to know how to create a wrapper library and let the users link their application with this library only. Users don't need to specify the original library in their linker flags.
For instance, I create a wrapper library for libwebsockets, named libcustomws.
add_library(customws main.c)
target_link_libraries(customws websockets)
I would like user (with no libwebsockets installed) to be able to do:
add_executable(user_app user_app.c)
target_link_libraries(user_app customws pthread)
Wrapper libraries without any additional code from within your project can best be implemented with small INTERFACE library targets with the IMPORTED tag. Example for your scenario:
add_library(customws INTERFACE IMPORTED)
target_include_directories(customws
INTERFACE
/some/include/path)
target_link_libraries(customws
INTERFACE
websockets)
This way, targets that use this library can just
add_executable(user_app user_app.c)
target_link_libraries(user_app customws pthread)
and get the usage requirements from the target customws, in this case an include directory and a linked library (websockets) are propagated through customws. This can be a good thing, as it might encapsulate implementation details of the dependency (different flags for different platforms etc.).
If you like to automatically link to compiled code (that is part of your project), this can be easily done by adding a small intermediate OBJECT library, e.g.
add_libraray(customwsenhanced
OBJECT
someCode.c)
target_link_library(customwsenhanced
PUBLIC
customws)
Depending on whether someCode.c depends on the usage requirements of customws, the target_link_library for customwsenhanced could also use INTERFACE propagation. Now, a client application can go with
add_executable(user_app user_app.c)
target_link_libraries(user_app customwsenhanced pthread)
and will get both the compiled object code of someCode.c as well as flags etc. from customws.

Transitive dependencies and OBJECT libraries

A somewhat similar question was asked here, Transitive target_include_directories on OBJECT libraries, but there was no real solution.
If I have a project b that depends on a project a I can build them as follows
add_library(a OBJECT ${a_srcs})
add_library(b OBJECT ${b_srcs})
When I want to build an excutable using I them I can write
add_executable(p ${p_srcs} $<TARGET_OBJECTS:b> $<TARGET_OBJECTS:a>)
Is there any way to not have to specify $<TARGET_OBJECTS:a>? I assume this means telling CMake in some way that there is a dependency. If I was building SHARED libraries rather than OBJECT ones the b project would contain
target_link_libraries(b a)
which creates this dependency, but I can't find some equivalent way for OBJECT libraries.
Insofar as I understand it, in the current setup, no. The add_executable for target p can either
Link against some library (shared or static), or
Merge object sources into itself.
You have chosen (2). The only other option I see here is create a third library c that merges in a and b into a full-blown library (see Usage section at the bottom, which is likely where you were already looking).
When you do that, you could then target_link_libraries(c). The compiled OBJECTs cannot be linked against on their own. You have to merge the sources into either an executable or a library for them to be used.
Your add_executable call could be thought of basically doing add_executable(p ${p_srcs} ${a_srcs} ${b_srcs}), only instead of compiling a_srcs and b_srcs (which has been done previously), just copy in the compiled objects instead of redoing the work. That's a really simple / bad explanation, but that's the general idea.
The best way I have found to do this is to wrap the OBJECT library in an INTERFACE library.
add_library(a-objects OBJECT ${a_srcs})
add_library(b-objects OBJECT ${b_srcs})
add_library(a INTERFACE)
add_library(b INTERFACE)
target_link_libraries(a INTERFACE a-objects)
target_link_libraries(b INTERFACE b-objects)
target_sources(a INTERFACE $<TARGET_OBJECTS:a-objects>)
target_sources(b INTERFACE $<TARGET_OBJECTS:b-objects>)
My rule is to use the OBJECT library to set requirements, but only ever link against the INTERFACE library.
target_link_libraries(b-objects INTERFACE a)
Setting it up this way should allow you to link against both libraries like this:
add_executable(p ${p_srcs})
target_link_libraries(p PRIVATE b)

Compile-time warning about missing category method implementation

In our Xcode project we have multiple targets which share some common code. Each target includes only sources which are actually used by it. So when we use some category methods inside classes which are shared between targets we need to make sure that this category implementation is also included in all targets. Xcode doesn't show any warnings during compile time or link time if we forget to include category implementation to some of the targets. And it is troublesome to do it by hand.
Is there any automated way to ensure that category implementations are included to the targets which use them?
Categories are not automatically linked to the final binary.
They are linked if the linker finds the file where they are defined is used (which was a source of constant bug some times ago).
What you can do is use a special flag on the linker: '-all_load' and '-ObjC' in Build Settings/Linking/Other Linker flags
-ObjC Loads all members of static archive libraries that implement an Objective-C class or category.
And from this discussion:
-all_load and -force_load tell the linker to link the entire static archive in the final executable, even if the linker thinks that parts
of the archive are unused.
Another way I use to force link the module is to put a C function in the file:
void _linkWithNBLogClass(void)
{
NSLog(#"%s", __FUNCTION__);
}
and call it at the start of my application:
linkWithNBLogClass();
This way, by the console feedback, I'm sure my module is loaded and ready to be used.
The described behavior is as intended and much existing code would break, if it is changed.
Prior to formal protocols there was a need to declare methods without defining them. This was for optional methods, i. e. for declaring a delegate API. The usual technique was to declare a so-called informal protocol, consisting of a category on NSObject that is never implemented.
But if you have a category implementation, of course the completeness of it is checked against the category interface. (Otherwise you get a "Method definition for X is not found" error.) So you do not have a missing method in the category implementation, but a missing category implementation.
I do not think that this is a big deal. You will get a runtime error instead of a compile time error and simply add the category implementation to the target.

Xcode xcconfig: Configuring a dependency based on the target

In the quest to resolve the Objective-C namespace issue I'd like to experiment with prefixing a dependency's Objective-C classes based on the target being built.
As an example, suppose I have in my shared library (ObjCStaticLib) a class (CWindow). I have two plugins (A and B) that will use this CWindow. To avoid A's CWindow from colliding with B's CWindow, I want to prefix the CWindow class name at compile time, so A's CWindow becomes ACWindow and B's becomes BCWindow.
I'm looking for a way to communicate to ObjCStaticLib at compile time what prefix it should use to compile itself with. I'm thinking about using xcconfigs to specify a preprocessor macro that the leaf target customizes and that ObjCStaticLib uses. However, I'm not aware of a way for a target to "communicate" with a dependency like that.
I can modify all the sources/projects/etc involved as necessary to implement per-client namespace customization in a dependency.
Does anyone have a good solution for this?