To effectively use cmkr it helps to understand the basic concepts of CMake.
A CMake project is a collection of targets. In the context of libraries the project usually corresponds to the package that other projects can depend on.
Visual Studio: a CMake project corresponds to a solution.
The basic unit of CMake is called a target. A target (also referred to as binary target in the CMake documentation) corresponds to an executable or library you can build. There are also pseudo targets, but we ignore them for now.
Visual Studio: a target corresponds to a project.
Targets have a collection of properties that describe how to build them.
Examples of properties:
- Sources: the
*.cppfiles used to build the target.
- Compile options: Command line flags for the compiler.
- Link libraries: The dependencies required to build this target.
See the CMake documentation for an exhaustive list of target properties.
Important: The term link has a slightly different meaning in CMake than you might expect. In addition to adding a library to the command line of the linker, CMake also propagates properties of the target you link to.
You can think of linking as depending on.
The propagation of properties depends on their visibility:
- Private: properties that are only used when building the target itself.
- Interface: properties that are used when depending on this target.
- Public: combination of private and interface.
In practice you default to private, unless consumers of your library require the property to build their target. In that case you use public.
The most intuitive example is with include directories. Imagine there are two targets:
StringUtils: A library with string utilities.
- Include directories:
DataProcessor: An executable that uses functionality from
StringUtilsto process some data.
- Link libraries:
The include directories property of
StringUtils has to be public. If it was private, the
DataProcessor target would fail to
#include <stringutils.hpp> since the include directories property is not propagated.
cmake.toml for this example would look something like this:
[project] name = "DataProcessor" [target.StringUtils] type = "static" sources = ["StringUtils/src/stringutils.cpp"] headers = ["StringUtils/include/stringutils.hpp"] include-directories = ["StringUtils/include"] [target.DataProcessor] type = "executable" sources = ["DataProcessor/src/main.cpp"] link-libraries = ["StringUtils"]