English | 中文版
[TOC]
- Do not use functions with global scope, such as
link_directories,include_libraries, etc. - Do not add unnecessary PUBLIC requirements.
- Do not add GLOB files in the file function.
- Link libraries directly to the targets that need to be built; if possible, always explicitly link libraries to targets.
- When linking libraries, do not omit the PUBLIC or PRIVATE keyword; omitting them will cause all subsequent links to default.
- Commands are case-insensitive, but parameters and variables are case-sensitive. It is recommended to use uppercase for variables, lowercase for functions and macros.
- Variables are accessed using
${}syntax, but in IF control statements, use the variable name directly. - System variables are accessed using
ENV{varname}. - Command format:
command(param1 param2 ...). - make does not support make distclean.
- In CMake, C++ is the default programming language; to compile other languages, use the
LANGUAGESoption explicitly. - When using the cmake command, set options with
-D, and use-Gto set the generator. - Use
EQUALfor string comparison.
if(<condition>)
<commands>
elseif(<condition>)
<commands>
else()
<commands>
endif()Conditions include:
-
Basic expressions
condition Description 1
ON
YES
true
Y
nonzero valuetrue 0
OFF
NO
false
N
IGNORE
NOTFOUND
empty string
xxx-NOTFOUNDfalse -
Logical expressions
condition Description NOT NOT AND AND OR OR -
Extended checks
condition Description COMMAND True if the given name is a callable command, macro, or function POLICY True if the given name is an existing policy (format CMP) TARGET True if the given name is a logical target created by add_executable(), add_library(), or add_custom_target() in any directory TEST True if the given name is a test created by add_test() (since 3.3) DEFINED True if a variable with the given <name>existsCACHE{} True if a cache variable with the given <name>existsENV{} True if an environment variable with the given <name>existsIN_LIST True if the given element is in the named list variable (since 3.3) -
File operations
condition Description EXISTS True if the specified file or directory exists IS_NEWER_THAN True if file1 is newer than file2 or if either file does not exist IS_DIRECTORY True if the given name is a directory
Use IF for conditional control.
Example:
set(ok 0)
set(ok OFF)
set(ok NO)
set(ok false)
set(ok N)
set(ok IGNORE)
set(ok NOTFOUND)
set(ok "")
set(ok xxx-NOTFOUND)
if (ok)
message("do ok")
else()
message("do fail")
endif()while(<condition>)
<commands>
endwhile()Loop executes commands while the condition is true.
Iterate over lists, with 4 usage patterns:
- Use
foreach(loop_var arg1 arg2 ...)to provide a loop variable and explicit item list (if the item list is in a variable, it must be expanded, i.e.,${sources_with_lower_optimization}must be passed as a parameter). - Specify a range to loop over integers // ...existing code...
- Loop over list value variables // ...existing code...
- Loop over variables // ...existing code...
Example:
list(
APPEND hello_src
)
foreach(f IN LISTS hello_src)
...
endforeach()Makefile: make will run commands to build the projectCMakefile: directory containing temporary files, CMake uses it to detect OS, compiler, etc.cmake_install.cmake: CMake script handling install rules, used during project installationCMakeCache.txt: CMake cache, used when re-running configuration
ADD_COMPILE_DEFINITIONS
TODO
ADD_COMPILE_OPTIONS
TODO
ADD_CUSTOM_COMMAND
add_custom_command(OUTPUT output1 [output2 ...]
COMMAND command1 [ARGS] [args1...]
// ...existing code...
[COMMAND_EXPAND_LISTS])Execute a command.
Example:
add_custom_command(
Setup ALL hello.exe /V1 hello.nsi
// ...existing code...
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)ADD_CUSTOM_TARGET
TODO
ADD_DEFINITIONS
add_definitions(-DFOO -DBAR ...)Add compiler command line definitions (flags defined by -D).
add_definitions(-DABC -DHELLO)#ifdef ABC
...
#endif
#ifdef HELLO
...
#endifADD_DEPENDENCIES
add_dependencies(<target> [<target-dependency>]...)target: top-level targettarget-dependency: dependency
Add a dependency between top-level targets.
add_subdirectory(lib1)
add_dependencies(hello lib1)ADD_EXECUTABLE
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...]) Generate an executable.
add_executable(<name> IMPORTED [GLOBAL])Import an executable.
add_executable(<name> ALIAS <target>)Alias an executable.
Example:
add_executable(hello
main.c
)ADD_LIBRARY
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[<source>...])- STATIC: static library
- SHARED: shared library
- OBJECT: object file
- MODULE: DSO group (for dynamic loading, runtime plugins; not linked to any project target)
- IMPORTED: immutable library (for building existing dependencies)
- INTERFACE: interface library (for use by targets outside the project)
- ALIAS: alias (for defining an alias for an existing library target)
Create a library (dynamic/static/object/...).
add_library(<name> OBJECT [<source>...])Create an object file dependency library.
add_library(<name> OBJECT [<source>...])Create an interface dependency.
add_library(<name> <type> IMPORTED [GLOBAL])Import a dependency.
Example:
# Create hello.lib
add_library(hello
STATIC
)ADD_LINK_LIBRARY
link_libraries([item1 [item2 [...]]]
[[debug|optimized|general] <item>] ...)Link dependency files (libs) to executables at link time.
target_link_libraries(hello
PRIVATE
)ADD_LINK_OPTIONS
add_link_options(<option> ...)Add options to executables, shared libraries, or module library targets in the current and subdirectories during the link step.
ADD_SUBDIRECTORY
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
source_dir: subdirectory of source filesbinary_dir: build output (intermediate build results) pathEXCLUDE_FROM_ALL: exclude this directory from the build process
Add a subdirectory containing source files to the current project, optionally specifying where to store intermediate and target binaries.
ADD_SUBDIRECTORY(sub_dir)ADD_TEST
add_test(NAME <name> COMMAND <command> [<arg>...]
[CONFIGURATIONS <config>...]
// ...existing code...
[COMMAND_EXPAND_LISTS])COMMAND: command lineCONFIGURATIONS: configurationWORKING_DIRECTORY: working directoryCOMMAND_EXPAND_LISTS: expand COMMAND parameter (added in 3.16)
Add a test (see CTest).
AUX_SOURCE_DIRECTORY
aux_source_directory(<dir> <variable>)Collect all source file names in the specified path and store the output list in the specified variable.
aux_source_directory(. HELLO_SRC) # Find all source files in the current directory and save to HELLO_SRCCMAKE_DEPENDENT_OPTION
cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>)Define an option that depends on other options.
cmake_dependent_option(
MAKE_STATIC_LIBRARY "compile static library" OFF # OFF depends on USE_LIBRARY=ON
"USE_LIBRARY" ON
)cmake -DUSE_LIBRARY=ON .. # MAKE_STATIC_LIBRARY=OFFCMAKE_MINIMUM_REQUIRE
cmake_minimum_required(VERSION <min>[...<policy_max>] [FATAL_ERROR])Minimum CMake version requirement.
cmake_minimum_required()
cmake_minimum_required(VERSION 3.24.1)CONFIGURE_FILE
Configure file with source version check.
configure_file(hello.h.in hello.h)ENABLE_TESTING
configure_file(<input> <output>
[NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
// ...existing code...
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])Enable testing for the current and subdirectories.
EXEC_PROGRAM
exec_program(Executable [directory in which to run]
[ARGS <arguments to executable>]
// ...existing code...
[RETURN_VALUE <var>])Whether to build the test target, involving all project directories.
EXECUTE_PROCESS
Execute a command and get its result.
find_package(GIT QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
// ...existing code...
endif()
endif()FILE
Reading
file(READ <filename> <out-var> [...])
// ...existing code...
file(GET_RUNTIME_DEPENDENCIES [...])
Writing
file({WRITE | APPEND} <filename> <content>...)
// ...existing code...
file(CONFIGURE OUTPUT <output-file> CONTENT <content> [...])
Filesystem
file({GLOB | GLOB_RECURSE} <out-var> [...] [<globbing-expr>...])
// ...existing code...
file(CHMOD_RECURSE <files>... <directories>... PERMISSIONS <permissions>... [...])
Path Conversion
file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE])
// ...existing code...
file({TO_CMAKE_PATH | TO_NATIVE_PATH} <path> <out-var>)
Transfer
file(DOWNLOAD <url> [<file>] [...])
file(UPLOAD <file> <url> [...])
Locking
file(LOCK <path> [...])
Archiving
file(ARCHIVE_CREATE OUTPUT <archive> PATHS <paths>... [...])
file(ARCHIVE_EXTRACT INPUT <archive> [...])File operation commands.
FIND_PACKAGE
- TODO: library name
- TODO: minimum library version
- REQUIRED: module is required (fail if not found)
- COMPONENTS: list of libraries to find
Search for CMAKE modules in the folders listed in CMAKE_MODULE_PATH with the format Findxxx.cmake.
find_package(Boost 1.80.0 REQUIRED COMPONENTS filesystem system)FIND_PATH
find_path (
<VAR>
// ...existing code...
)NAMES: specify one or more possible names for files in the directoryHINTS, PATHS: directories to searchPATH_SUFFIXES: specify extra subdirectories to check under each directory, otherwise invalidDOC: documentation string for the<VAR>cache entryNO_CACHE: store the result in a normal variable, not a cache entry (since 3.21)REQUIRED: stop processing and error if nothing is found, otherwise will try again on next call (since 3.18)CMAKE_FIND_ROOT_PATH_BOTH: search as aboveNO_CMAKE_FIND_ROOT_PATH: do not useCMAKE_FIND_ROOT_PATHONLY_CMAKE_FIND_ROOT_PATH: only search re-rooted directories and underCMAKE_STAGING_PREFIX
Find the directory containing the named file.
FIND_LIBRARY
find_library (
<VAR>
// ...existing code...
)This command is used to find libraries.
INCLUDE
include(<file|module> [OPTIONAL] [RESULT_VARIABLE <var>]
[NO_POLICY_SCOPE])Load and run CMake code from a file or module.
INSTALL
INSTALL(TARGETS targets ... [[ARCHIVE|LIBRARY|RUNTIME]] [DESTINATION <dir>] [PERMISSIONS permissions ...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL]])
PERMISSIONSOWNER_EXECUTEOWNER_WRITEOWNER_READGROUP_EXECUTEGROUP_READCMAKE_INSTALL_PREFIX: install location- TODO
Define install rules.
INSTALL(TARGETS myrun mylib mystaticlib
RUNTIME DESTINATION bin # Executable myrun installed to ${CMAKE_INSTALL_PREFIX}/bin
// ...existing code...
ARCHIVE DESTINATION libstatic # Static library libmystaticlib installed to ${CMAKE_INSTALL_PREFIX}/libstatic
)LIST
Compose file lists.
list(
APPEND hello_src
)MACRO
macro(<name> [<arg1> ...])
<commands>
endmacro()Start recording a macro for later invocation as a command (invocation is case-insensitive).
Example:
macro(hello)
...
endmacro()
Hello()MESSAGE
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)
SEND_ERROR: error, skip generationSTATUS: output with prefixFATAL_ERROR: immediately terminate all cmake processes
Output information to the terminal.
OPTION
OPTION(<NAME> "MESSAGE" [VALUE])
NAME: variable nameMESSAGE: descriptionVALUE: default value (ON/OFF)
Used to accept parameters from the command line.
option(hello "hello world" ON)PROJECT
PROJECT(target_name LANGUAGES language)
LANGUAGES: programming language (default C++).
Declare project name.
project(HELLO)Specify project name.
SET
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])
Set variable value.
SET(SRC_LIST main.c t1.c t2.c)SET_TARGET_PROPERTIES
set_target_properties(target1 target2 ...
PROPERTIES prop1 value1
prop2 value2 ...)Set properties for generated targets.
set_target_properties(hello
PROPERTIES
)SET_TESTS_PROPERTES
set_tests_properties(test1 [test2...] PROPERTIES prop1 value1 prop2 value2)prop*: key- TIMEOUT
Set test parameters.
set_tests_properties(helo PROPERTIES TIMEOUT 10) # Set test timeoutSUBDIRS
SUBDIRS(dir1 dir2 ...)
Add multiple subdirectories at once (not recommended).
TARGET_COMPILE_DEFINITIONS
Pass target compile flags to other targets according to scope.
target_compile_definitions(hello_flags
PRIVATE EX3
)TARGET_COMPILE_FEATURES
Set C++ standard.
target_compile_features(hello PUBLIC cxx_auto_type)TARGET_COMPILE_OPTIONS
Set compile options.
target_compile_options(hello PRIVATE ${hello_flags})TARGET_LINK_LIBRARIES
TARGET_LINK_LIBRARIES[TARGETS SOURCE]
TARGETS: executable targets to link toSOURCE: target library
Link target library to executable target.
target_link_libraries(hello hello_lib)TARGET_INCLUDE_DIRECTORIES
PRIVATE: add directory to this target's include directoriesINTERFACE: add directory to any target linking to this library (not itself)PUBLIC: included in this library and any target linking to it
Add header file directories to the compiler, used in:
- When compiling the library
- When compiling any other target linking to the library
target_include_directories(hello
PRIVATE
)TARGETS
Generated target names.
CMake provides function for custom functions.
function(<name> [arg1 [arg2 [arg3 ...]]])
COMMAND1(ARGS ...)
// ...existing code...
...
endfunction(<name>)<name>: function namearg1, arg2...: function parameters
Example:
set(x "ABC")
set(y "DEF")
function(F1 arg)
message(arg "abc" PARENT_SCOPE)
endfunction()
function(F2 arg)
message(${arg} "def" PARENT_SCOPE)
endfunction()
Foo(${x}) # pass by value
Foo(y) # pass by referenceCMake defines some implicit parameters for function:
| Implicit Param | Description |
|---|---|
| ARGC | Number of actual arguments |
| ARGV | List of all actual arguments |
| ARGN | All extra arguments, i.e., ARGV minus explicitly declared ones |
| ARGV0 | First argument |
| ARGV1 | Second argument |
| ARGV2 | Third argument |
| ... | ... |
Example:
function(print_list arg)
message("======= args count : ${ARGC} ======= ") # Number of actual arguments
// ...existing code...
endforeach()
endfunction()
set(arg hello world)
message("------------ calling with quotes -----------") # Call with quotes
print_list("${arg}")
message("------------ calling without quotes -----------") # Call without quotes
print_list(${arg})CMAKE_MAJOR_VERSION: major versionCMAKE_MINOR_VERSION: minor versionCMAKE_PATCH_VERSION: patch levelCMAKE_SYSTEM: system nameAPPLE: macOS // ...existing code...MINGW: mingw environment
CMAKE_SYSTEM_NAME: system name without versionCMAKE_SYSTEM_VERSION: system versionCMAKE_SYSTEM_PROCESSOR: processor nameHOME
MSVC
CMAKE_BINARY_DIR: directory for generated binariesCMAKE_RUNTIME_OUTPUT_DIRECTORY: path for executablesCMAKE_CURRENT_BINARY_DIR: current build directoryCMAKE_CURRENT_LIST_FILE: full path of the current list file being processedCMAKE_CURRENT_LIST_LINE: line number in the current file being processedCMAKE_CURRENT_SOURCE_DIR: current source directoryCMAKE_INCLUDE_CURRENT_DIR: whether to add current source and build directories to include pathCMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE: force project include dirs to be prependedCMAKE_INCLUDE_PATHCMAKE_LIBRARY_PATHCMAKE_MODULE_PATHCMAKE_PROJECT_NAME: name of the first (top-level) project set byproject()CMAKE_SOURCE_DIR: root source directoryEXECUTABLE_OUTPUT_PATH: path for generated executablesLIBRARY_OUTPUT_PATH: path for shared libraries (only effective if default path not set)CMAKE_ARCHIVE_OUTPUT_DIRECTORY: default path for static librariesCMAKE_LIBRARY_OUTPUT_DIRECTORY: default path for dynamic librariesPROJECT_BINARY_DIR: current project's build directoryPROJECT_NAME: project namePROJECT_SOURCE_DIR: current cmake project's source directoryxxx_SOURCE_DIR: source directory for project xxxxxx_BINARY_DIR: binary directory for project xxx
BUILD_SHARED_LIBS: controls default library build type (default is static)CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS: controls if/else statement syntaxCMAKE_BUILD_TYPE: build typeCMAKE_C_FLAGS: C compiler flagsCMAKE_CXX_COMPILER: which C++ compiler to useclang++: use clang
CMAKE_CXX_FLAGS: C++ compiler flags-std: compiler version
CMAKE_CXX_STANDARD: C++ standard flag (since v3.1)CMAKE_LINKER_FLAGS: linker flags
TODO
TODO
Define an option in CMakeLists.txt to accept parameters from the command line, then pass it to C++ files.
# Define option
option(LOG_TABLE "select to use log table" OFF)
# Pass to C++ file
if(LOG_TABLE)
add_definitions(-DLOG_TABLE=on)
endif(LOG_TABLE)Command line:
cmake -DLOG_TABLE=ON ..set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEX2" CACHE STRING "Set C++ Compiler Flags" FORCE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # Use C++11
set(CMAKE_CXX_STANDARD 11) # Use C++11 standardcmake -DCMAKE_CXX_COMPILER=clang++ .. # Use clangTODO
CMake 3.11+ provides the FetchContent module for dependency management.
FetchContent_Declare() is used to fetch data or packages from URLs, Git repositories, etc.
FetchContent_GetProperties() is used to get package info.
xxx_POPULATED is used to check if a variable is exported (content populated).
ExternalProject_Add() is used to download during build; the main and external projects are only called the first time CMake runs.
ExternalProject_Add provides options for configuring and building external projects:
- Directory: tune source structure and build directory for external project
- Download: code may need to be downloaded from online repositories or resources
- Update and Patch: define how to update or patch external project source
- Configure: if the external project is a CMake project,
ExternalProject_Addwill call CMake and pass options - Build: adjust actual build of external project
- Install: configure how to install external project
- Test: run tests for source-based builds
- URL: HTTP address for archive
- GIT_REPOSITORY: Git repo for dependency source
- GIT_TAG: branch to checkout
- SVN_REPOSITORY: SVN repo for dependency source
- HG_REPOSITORY: Mercurial repo for dependency source
- TEST_AFTER_INSTALL: run tests after install
- TEST_BEFORE_INSTALL: run tests before install
- TEST_EXCLUDE_FROM_MAIN: remove dependency on main target from test suite
include(FetchContent) # Include FetchContent module
FetchContent_Declare( # Declare external content
hello
// ...existing code...
GIT_TAG main
)
FetchContent_Populate( # Declare external content
firmware
// ...existing code...
SOURCE_DIR firmware
)
# CMake 3.14+
FetchContent_MakeAvailable(hello)
# CMake 3.14-
FetchContent_GetProperties(hello) # Check if content is populated
if(NOT hello_POPULATED) # Not populated
FetchContent_Populate(hello) # Populate content
// ...existing code...
)
endif()TODO
TODO
CMake 3.5+ provides CTest for unit testing.
CTest convention: return zero means success, nonzero means failure; any script returning zero/nonzero can be a test case.
Use these options for more detailed CTest output:
--output-on-failure: print any output from test program to screen if test fails-v: enable verbose output-vv: enable more verbose output--rerun-failed: rerun previously failed tests
Example:
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(hello_test LANGUAGES CXX)
find_package(PythonInterp REQUIRED)
find_program(BASH_EXECUTABLE NAMES bash REQUIRED)
add_executable(hello_test test.cpp)enable_testing() # Test this directory and all subfolders
# Set test environment variables
set_tests_properties(python_test
PROTERTIES
)
# Define a new test
add_test(
NAME hello_test # Set test name
COMMAND $<TARGET_FILE:hello_test> # Run command with generator expression
)
# Set test duration
set_tests_properties(hello PROPERTIES TIMEOUT 10)ctestCMake also supports these other unit test tools:
-
Internal build
- TODO
-
External build
// ...existing code... 4. Run
maketo build the project.
CMAKE_BUILD_TYPE build types:
- Debug: build with debug symbols, no optimization
- Release: optimized build, no debug symbols
- RelWithDebInfo: less optimized build with debug symbols
- MinSizeRel: optimized for minimum code size
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build Type" FORCE)cmake --build . --target <target-name>
target// ...existing code...package
Build the project.
TODOTODO
CPack is used to generate packages. CPack commands are listed in CMakeCPack.cmake, which generates CPackConfig.cmake. When running CMake with the package or package_source target, CPack is called automatically.
- CPACK_PACKAGE_NAME: name
- CPACK_PACKAGE_VENDOR: vendor
- CPACK_PACKAGE_DESCRIPTION_FILE: description file
- CPACK_PACKAGE_DESCRIPTION_SUMMARY: package description
- CPACK_RESOURCE_FILE_LICENSE: license file
- CPACK_PACKAGING_INSTALL_PREFIX: install path
- CPACK_PACKAGE_VERSION_MAJOR: major version
- CPACK_PACKAGE_VERSION_MINOR: minor version
- CPACK_PACKAGE_VERSION_PATCH: patch version
- CPACK_SOURCE_IGNORE_FILES: files/directories to ignore
- CPACK_SOURCE_GENERATOR: archive format
- CPACK_GENERATOR: packaging tool
- CPACK_DEBIAN_PACKAGE_MAINTAINER
- CPACK_DEBIAN_PACKAGE_SECTION
- CPACK_NSIS_CONTACT
- CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL: uninstall before install
- CPACK_BUNDLE_NAME: bundle name
- CPACK_BUNDLE_PLIST:
*.plistfile - CPACK_BUNDLE_ICON: icon
- linux TODO
- macos
// ...existing code...
- Bundle
- windows
// ...existing code...
- NSIS
# Declare package name
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
# Declare package vendor
set(CPACK_PACKAGE_VENDOR "hello")
# Package description file
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/INSTALL.md")
# Add package description
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "hello")
# Add license file
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
# Set install path to /usr/local/hello
set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local/${PROJECT_NAME}")
# Set major, minor, and patch version
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
# Set files/directories to ignore during packaging
set(CPACK_SOURCE_IGNORE_FILES "${PROJECT_BINARY_DIR};/.git/;.gitignore")
# Set archive format
set(CPACK_SOURCE_GENERATOR "ZIP;TGZ")
# Set binary archive generator
set(CPACK_GENERATOR "ZIP;TGZ")
# Declare native binary installer for linux
if(UNIX)
if(CMAKE_SYSTEM_NAME MATCHES Linux)
// ...existing code...
endif()
endif()
# Declare native binary installer for windows
if(WIN32 OR MINGW)
list(APPEND CPACK_GENERATOR "NSIS") # nsis installer
// ...existing code...
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
endif()
# Declare native binary installer for macos
if(APPLE)
list(APPEND CPACK_GENERATOR "Bundle") # bundle
// ...existing code...
set(CPACK_BUNDLE_ICON ${PROJECT_SOURCE_DIR}/cmake/coffee.icns)
endif()
# Print info
message(STATUS "CPack generators: ${CPACK_GENERATOR}")
include(CPack)PROTOBUF_FOUND: whether protobuf is installedPROTOBUF_INCLUDE_DIRS: protobuf header directoryPROTOBUF_LIBRARIES: protobuf library directory
PROTOBUF_GENERATE_CPP(SRCS HDRS *.proto)
SRCS: stores.pb.ccfile namesHDRS: stores.pb.hfile names*.proto: proto files
if(PROTOBUF_FOUND) # protobuf installed?
...
endif()
PROTOBUF_GENERATE_CPP(hello hello hello.proto)(For details, see \share\cmake-xxx\Modules\FindBoost.cmake in the cmake install dir, or the official docs: https://cmake.org/cmake/help/v3.6/module/FindBoost.html)
Boost info variables:
- Boost_FOUND: whether required libraries found
- Boost_INCLUDE_DIRS: boost header search path
- Boost_LIBRARY_DIRS: boost library link path
- Boost_LIBRARIES: boost library names for linking
- Boost_VERSION: version from boost/version.hpp
- Boost_LIB_VERSION: version of a sublibrary
Boost options:
- Boost_USE_STATIC_LIBS
- Boost_USE_MULTITHREADED
- Boost_USE_STATIC_RUNTIME
Set these environment variables to help find boost:
- BOOST_ROOT: preferred boost install path
- BOOST_INCLUDEDIR: preferred header search path
- BOOST_LIBRARYDIR: preferred library search path
To use Boost unit testing:
- Add boost component
unit_test_framework - Add link dependency
Boost::unit_test_framework - Define compile option
BOOST_TEST_DYN_LINK - Define unit test
find_package(Boost 1.80 REQUIRED COMPONENTS unit_test_framework)
target_link_libraries(hello
PRIVATE
)
target_compile_definitions(hello
PRIVATE
)
enable_testing()
add_test(
NAME boost_test
COMMAND $<TARGET_FILE:hello>
)#define BOOST_TEST_MODULE xxx
#include <boost/test/included/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(xxx)
BOOST_AUTO_TEST_CASE(xx)
{
BOOST_CHECK(...)
}
BOOST_AUTO_TEST_SUITE_END()TODO
Microsoft supports CMake in VS2017+. To enable Visual Studio CMake support, install the "C++ CMake tools for Windows" component.
To build different VS project versions, specify the VS generator and architecture:
cmake -G "<platform>" -A <architecture>platform: VS generator- "Visual Studio 6" // ...existing code...
- ...
architecture: architecture- Win32 // ...existing code...
- ...
Example:
cmake -G "Visual Studio 17 2022" -A x64General variables:
- CMAKE_AUTOMOC: process .moc files?
- CMAKE_AUTORCC: process .qrc files (resources)?
- CMAKE_AUTOUIC: process .ui files (UI)?
- CMAKE_INCLUDE_CURRENT_DIR: moc search dir
Module variables:
- Qt5Widgets_COMPILE_DEFINITIONS: compile options
- Qt5Widgets_DEFINITIONS: dependency options
- Qt5Widgets_EXECUTABLE_COMPILE_FLAGS: executable options
- Qt5Widgets_FOUND: found Widgets module?
- Qt5Widgets_INCLUDE_DIRS: Qt widgets dir (QtCore and QtGui depend on this)
- Qt5Widgets_LIBRARIES: Qt widgets dependency dir
- QtWidgets_PRIVATE_INCLUDE_DIRS: Qt Widgets private dir
- QtWidgets_VERSION_STRING: module version
- Qt5Declarative_INCLUDE_DIRS: Qt Declarative dir
- Qt5Declarative_LIBRARIES: Qt Declarative dependency dir
Install variables:
- QT_DEFAULT_MAJOR_VERSIO: default major version (Qt5/Qt6)
- QT_LIBINFIX: dependency infix
- QT_NO_CREATE_VERSIONLESS_FUNCTIONS: fix function version compatibility (Qt5.15+, qt functions are versionless, e.g.
qt5_becomesqt_) - QT_NO_CREATE_VERSIONLESS_TARGETS: fix module version compatibility (Qt5.15+, qt modules are versionless, e.g.
Qt5::becomesQt::) - QT_VISIBILITY_AVAILABLE: export symbols?
Qt5::Core:
- qt5/qt_add_big_resources: add big resource files
- qt5/qt_add_binary_resources: create RCC files from qt resource files
- qt5/qt_add_resources: add binary resource files
- qt5/qt_generate_moc: call input .moc files
- qt5/qt_import_plugins: add qt static plugins
- qt5/qt_wrap_cpp: create .moc files from source
Qt5::DBus
- qt_add_dbus_adaptor
- qt_add_dbus_interface
- qt_add_dbus_interfaces
- qt_generate_dbus_interface
Qt5::LinguistTools
- qt5_add_translation: compile Linguist.ts to .qm
- qt5_create_translation: set up lightweight translation tool
Qt5::RemoteObjects
- qt5_generate_repc: create C++ classes from qt remote object .rep files
Qt5::Widgets
- qt5/qt_wrap_ui: create source from .ui files
-debug// ...existing code...-release// ...existing code...-debug-and-release
cmake_minimum_required(2.8.8)
project(hello)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()
find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_definitions(${Qt5Widgets_DEFINITIONS}) # -DQT_WIDGETS_LIB
# cmake2.8.8+ supports, equivalent to .pro:
# TARGET = hello
# QT += widgets declarative
qt5_use_modules(hello Widgets Declarative)
add_executable(${PROJECT_NAME}
hello.h
// ...existing code...
hello.ui
)
target_link_libraries(hello Qt5::Widgets)zeromq is an open-source third-party network library; cmake provides ways to integrate zeromq.
ZMQ_BUILD_TESTS: build test examplesBUILD_SHARED: build shared libraryBUILD_STATIC: build static library
Example:
cmake .. -DZMQ_BUILD_TESTS=OFF -DBUILD_STATIC=ON -DBUILD_SHARED=ONzmqpp is an excellent C++ wrapper for zeromq. Use CMake to integrate zmqpp. Common variables:
ZMQ_BUILD_TESTS: enable test?ZMQPP_BUILD_STATIC: build static library (default ON)ZMQPP_BUILD_SHARED: build shared library (default ON)ZMQPP_LIBZMQ_NAME_STATIC: zeromq static libZMQPP_LIBZMQ_NAME_SHARED: zeromq shared libZEROMQ_LIB_DIR: zeromq lib search pathZEROMQ_INCLUDE_DIR: zeromq header dir
Example:
cmake .. -G "Visual Studio 14 2015 Win64" -DZMQ_BUILD_TESTS=OFFValgrind is a general tool for detecting memory defects and leaks. CMake supports integrating Valgrind.
Example:
// main.cpp
#include <iostream>
int main() {
auto m = new double[1000]; // not freed
}cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(hello LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(hello_test main.cpp)
# Find valgrind and set absolute path MEMORYCHECK_COMMAND
find_program(MEMORYCHECK_COMMAND NAMES valgrind)
# Set valgrind options (create log file for memory defect info)
set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full")
include(CTest)
enable_testing()
add_test(
NAME hello_test
COMMAND $<TARGET_FILE:hello_test>
)ctest -T memcheck[1] CMake Tutorial
[2] Eric Noulard, Roberto Di Remigio.CMake-Cookbook
[3] Modern CMake Simplified Chinese
[4] An Introduction to Modern CMake
[6] Find Boost Library with CMake on Linux
[8] Build with CMake
[10] CMake Projects in Visual Studio
[12] CMake Syntax—Cache Variable