Reference:
modern_cmake_talks
a-list-of-common-cmake-antipatterns
cmake Introduction and best practices
Cmake official docs:
CMake_Useful_Variables
cmake latest doc
cmake-language.7.html#syntax
cmake-tutorial
How To Find Libraries
How To Write Platform Checks
VariablesListsStrings
RPATH handling
CMake FAQ
modern_cmake_talks
a-list-of-common-cmake-antipatterns
cmake Introduction and best practices
Cmake official docs:
CMake_Useful_Variables
cmake latest doc
cmake-language.7.html#syntax
cmake-tutorial
How To Find Libraries
How To Write Platform Checks
VariablesListsStrings
RPATH handling
CMake FAQ
FetchContent
Reference:
https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html
The major usage for downloading 3rd party library from source control.
https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html
The major usage for downloading 3rd party library from source control.
Antipattern:
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wextra")
- Debug build (Adding -g manually)
- Pass -DCMAKE_BUILD_TYPE=debug to CMake
- CMAKE_BUILD_TYPE / CMAKE_CONFIGURATION_TYPES
- This variable is only meaningful to single-configuration generators (such as Makefile Generators and Ninja)
- There are many per-config properties and variables (usually following clean SOME_VAR_<CONFIG> order conventions), such as CMAKE_C_FLAGS_<CONFIG>, specified as uppercase: CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL].
- DEBUG
- RELEASE
- RELWITHDEBINFO
- MINSIZEREL
- use find_library instead of writing:
- target_link_libraries(myexe -lsomesystemlib)
- Do not do:
- add_executable(myexe myexe.c myexe.h) // gcc/clang will find xxx.c 's xxx.h/hpp automatically.
- The only exception to this rule is when you generate header files as part of your build.
- Do not repeat this:
- target_link_libraries(myexe mylibrary)
add_dependencies(myexe mylibrary) // <==== NOT NECESSARY - Do not 'Invoking make targets' intently.
- Invoke targets directly in CMake.
Most custom commands have a DEPENDS option that can be used to invoke other targets. - Do Out-of-source build.
- Do not call out sed or shell pipelines in Cmakelists.txt. Call cmake in shell script.
- Do not invoke cmake multiple times. It's just _not_ necessary.
Ninja or make will detect src code changes.
Compiler and platform test results are cached in CMakeCache.txt
You can modify this file and re-run CMake.
CMake also provides graphical cache editors.
cmake[<options>]<path>
- If the specified path contains a CMakeCache.txt, it is treated as a build directory where the build system is reconfigured and regenerated.
- Otherwise the specified path is treated as the source directory and the current working directory is treated as build directory.
cmake-E<command>[<options>...] // cmake command mode
- Run cmake -E help for a summary of commands.
- $ cmake -E make_directorybuild
$ cmake -E chdir cmake -E time cmake
$ cmake -E time cmake build
use cmake to run the build system
- $ cmake --build build \ --target mylibrary \ --config Release \ --clean-first
cmake as a scripting language
- Resist the bash/perl/python temptation!
Parameters needed:
- cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
- Prefer the latest version of CMake.
- project(<name> VERSION <version> LANGUAGES CXX)
- CMake sets several variables based on project()
- Call to project() must be direct, not through a function/macro/include
- CMake will add a call to project() if not found on the top level
- add_subdirectory(<sourcedir> [<binarydir>])
- Embed projects as sub-projects.
- CMake creates a Makefile/Solution for each sub-project.
- The sub-project does not have to reside in a sub-folder.
- Make sure that all your projects can be built both standalone and as a sub-project of another project
- Don’t assume that your project root is the build root.
- Don’t modify global compile/link flags.
- Don’t make any global changes!
- find_package(Qt5 REQUIRED COMPONENTS Widgets)
- Finds preinstalled dependencies
- Can set some variables and define imported targets.
- Supports components
- Add an executable target
- add_executable(tool main.cpp xxx.cpp)
add_executable(my::tool ALIAS tool) - Add a library target
- add_library(foo static foo.cpp foo2.cpp)
add_library(my::foo ALIAS foo) - Libraries can be STATIC SHARED MODULE INTERFACE
- Default can be controlled with BUILD_SHARED_LIBS
- Always add namespace aliases for libraries.
https://stackoverflow.com/questions/46567646/cmake-usefulness-of-aliases - Don’t make libraries STATIC/SHARED unless they cannot be built otherwise.
- Leave the control of BUILD_SHARED_LIBS to your clients!
- PRIVATE Only used for this target
PUBLIC Used for this target and all targets that link against it
INTERFACE Only used for targets that link against this library - target_link_libraries()
- Set libraries as dependency.
- Things to follow
- Prefer to link against namespace targets.
- Specify the dependencies are private or public.
- Avoid the link_libraries() command.
- Avoid the link_directories() command.
- No need to call add_dependencies().
- target_include_directories()
- Set include directories.
- target_include_directories(foo PUBLIC include PRIVATE src)
- Things to follow
- Avoid the include_directories() command.
- target_compile_definitions()
- Set compile definitions (preprocessor constants).
- target_compile_definitions(foo PRIVATE SRC_DIR=${Foo_SOURCE_DIR} )
- Things to follow
- Avoid the add_definitions() command.
- Avoid adding definitions to CMAKE_<LANG>_FLAGS
- target_compile_options()
- Set compile options/flags.
- if (CMAKE_COMPILER_IS_GNUCXX) target_compile_options(foo PUBLIC -fno-elide-constructors)
endif() - Things to follow
- Wrap compiler specific options in an appropriate condition.
- Avoid the add_compile_options() command.
- Avoid adding options to CMAKE_<LANG>_FLAGS.
- target_compile_features()
- Set required compiler features.
- target_compile_features(
foo PUBLIC
cxx_auto_type
cxx_range_for
PRIVATE
cxx_variadic_templates) - CMake will add required compile flags.
- Errors if the compiler is not supported.
- Things to follow
- Don’t add -std=c++11 to CMAKE_<LANG>_FLAGS. ∙
- Don’t pass -std=c++11 to target_compile_options().
best practices:
- goal: no custom variables:
- # BAD
set(PROJECT foobar)
set(LIBRARIES foo)
if(WIN32)
list(APPEND LIBRARIES bar)
endif()
target_link_libraries(${Project} ${LIBRARIES} ) - # GOOD
target_link_libraries(foobar PRIVATE my::foo)
if(WIN32)
target_link_libraries(foobar PRIVATE my::bar)
endif() - don't use file(glob)!
- # BAD
file(GLOB sources ”*.cpp”)
add_library(mylib ${sources}) - file(GLOB) is useful in scripting mode.
- Don’t use it in configure mode
- list all sources explicitly (Explicit is better than implicit)
- add_library(
mylib
main.cpp
file1.cpp
file2.cpp) - goal: no custom functions
- Experience taught me: Most of the time it is a bad idea.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.