Modern CMake
From Stephen Kelly’s YouTube video and blog link, a quick overview of modern, reusable CMake: what we should use, and what we should not, for composable and terse CMake.
Note: we should define minimum version to ensure ‘Modern CMake’, and understand what CMake policies this might invoke.
Targets
Use target_*
:
target_include_directories
withPUBLIC
andPRIVATE
(-I/foo/bar
)target_compile_definitions
(-DSOME_DEF=1
)target_compile_options
(-O2 -fPIC
)target_link_libraries
(-l/path/to/lib
)
Don’t use
include_directories
add_definitions
as they have problems with scope and transitivity.
Variables
Avoid unnecessary variables:
- can leak
- not checked for correctness or content
Generator Expressions
Calculated at generation time.
Generators and conditions:
- could use
target_sources
to append conditionally (e.g. platform specific file), don’t use a variable and append to it as a list. - could use generator:
add_executable(hello
main.cpp
$<$<BOOL:${WIN32}>:windows.cpp>
$<$<NOT:$<BOOL:${WIN32}>>:windows.cpp>
)
Don’t use CMAKE_BUILD_TYPE
(e.g. CMAKE_BUILD_TYPE STREQUAL DEBUG
).
Use:
add_executable(hello
main.cpp
$<$<CONFIG:Debug>:debug_only.cpp>
$<$<NOT:$<CONFIG:Debug>>:release_only.cpp>
)
Properties
Prefer:
# Evaluated at 'generation time'
# compile with 'USE_THREADS' if 'WITH_THREADS' is on.
target_compile_definitions(hello PRIVATE
$<$<TARGET_PROPERTY:WITH_THREADS>:USE_THREADS>)
# Set at 'configuration time'
set_property(TARGET hello PROPERTY WITH_THREADS ON)
Aliases
Can be helpful for readability, e.g.:
add_library(boost::mpl
ALIAS boost_mpl
)
# consumed as
target_link_libraries(my_library
boost::mpl
)
Dependencies
Legacy pattern was:
find_package(...)
add_definitions(...)
include_directories(...)
set(CMAKE_CXX_FLAGS ...)
add_executable(...)
target_link_libraries(...)
but that is for old-style (external) packages that populate variables. We may still need to use this.
Modern CMake define IMPORTED
targets, so we just do:
find_package(foo REQUIRED)
add_executable(hello main.cpp)
target_link_libraries(hello
Foo::Core
)
Creating Packages
See the video here
Install ‘rich’ targets and export packages.