I'm new to CMake and trying to learn to use it for a simple project. If I have a CMakeLists.txt file that looks like this:
add_executable(alpha alpha.cpp)
add_executable(beta beta.cpp)
add_library(one STATIC one.cpp)
add_library(two STATIC two.cpp)
target_link_libraries(alpha one)
target_link_libraries(alpha two)
target_link_libraries(beta one)
target_link_libraries(beta two)
Is there a way to simplify this sort of pattern? What I would like is to define something like all_libraries that contains both one and two, and then only have to do one linking per binary. Is there a way to do it?
You can use interface libraries:
add_library(all_libraries INTERFACE)
target_link_libraries(all_libraries
INTERFACE
one
two
)
... then later ...
target_link_libaries(alpha PUBLIC all_libraries)
You can use variable:
set(all_libraries one two)
.. then later ..
target_link_libraries(alpha PUBLIC ${all_libraries})
Notes:
I would advise to always explicit specify the the PUBLIC, PRIVATE and INTERFACE keywords.
I would go with interface libraries. It's nice to have a big project, expose different mix of libraries as a single interface library, than you only link another big project against that interface. Gives nice control and look of it.
Related
Daniel Pfeifer, in his presentation "Effective CMake",
makes a point, that it is advisable to avoid variable
definitions as much as possible.
Now, how does one get properties into a variety of build
targets. That is, for example
target_include_directories(base_IncludeFlags
INTERFACE
first/dir
second/dir
...)
defines a set of include directories. Instead of defining
the exact same include directories for target_a, target_b,
and target_c, I would like to let those targets inherit
the include directories from 'base_target', with something like
target_link_libraries(target_a PUBLIC base_IncludeFlags)
target_link_libraries(target_b PUBLIC base_IncludeFlags)
target_link_libraries(target_c PUBLIC base_IncludeFlags)
where base_IncludeFlags is shall not be a real physical target,
rather something like an abstract base class or interface.
On the other hand, I do not want to use include_directories
since this affects all targets. Is it better to use foreach?
What is the most elegant way to do this? Shall I make base_target
a library and add dependencies?
What I want is a target that is not actually physically produced, but which propagates some common properties.
Exactly for that purpose CMake has INTERFACE library - container for different properties, which are propagated when this library is linked into another target.
Example:
# Create "container" target
add_library(base_target INTERFACE)
# Add some INTERFACE properties for that target
target_include_directories(base_target INTERFACE
first/dir
second/dir)
# Some 'other_target' (library or executable) may easily consume all common properties:
target_link_libraries(other_target PUBLIC base_target)
# Now 'other_target' has aforementioned include directories too.
# Instead of PUBLIC other linking types (PRIVATE, INTERFACE) may be used.
What is the most elegant way to do this?
Consider that CMake files are often read and edited by people who aren't experts in CMake. Rather than going for elegance, you may consider going for simplicity: keep it simple, stupid.
If you introduce abstractions, hidden implicit behavior of any kind, it will be harder for everybody to maintain the CMake file.
For me, simple in this case would mean copying (duplicating) the entries, if there are just 2-3. If there's more libraries, I'd put the headers in a variable. The "Effective CMake" presentation makes a point to avoid unnecessary, single-use variable definitions. I'd argue that this header list would be a helpful variable, and worth creating.
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)
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.
I'm just learning objective-c after a fair amount of experience with C#. One of the things I sorely miss is the ability to write extension methods in a separate project that I could reference in all of my projects. Here's some naive c#:
public static bool IsShortString(this string s) {
return s.length <= 3;
}
In Visual Studio, I could just add a reference, an using, and bam myString.IsShortString() would be a, rather useless, method.
So I think I want to write a static library, but I'm not sure where I'm going from there.
One additional question, if I do write this static library, will I be able to use all of the methods throughout various files in the library using one #import directive, or will I have to import each header individually?
What you are looking for is called Category, and it allows you to add some additional methods to existing classes. Check the reference http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html
You can create your own toolkit which is a static library containing categories you made. Common practice is to create one header file containing imports for all the headers in the lib, so when using it, you just do
#import "libName.h"
Also, when creating a static library containing categories it is important to include -all_load and -ObjC linker flags to your project.
The closest thing in objective-c is categories.
This is also a good tutorial on categories.
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?