1 Introduction
CMake is an open source, cross-platform C++ build tool. It declares build targets through platform- and compiler-independent configuration files. It supports Make, ninja, MSBuild and other underlying build tools. Most IDEs (such as CLion, Visual Studio, Visual Studio Code, etc.) also support CMake.
- Website: https://cmake.org/
- Official documentation: CMake Reference Documentation
- Official Tutorial: CMake Tutorial
2. Install
2.1 Windows
There are several ways to install CMake on Windows:
(1) Download the MSI installation file (such as cmake-3.25.2-windows-x86_64.msi) and install it according to the instructions.
(2) Download the compressed file (such as cmake-3.25.2-windows-x86_64.zip), and add the bin directory to the PATH environment variable after decompression.
(3) If Visual Studio is installed, you can install "C++ CMake Tools for Windows" through the Visual Studio Installer, as shown in the figure below.
2.2 Linux
There are several ways to install CMake on Linux:
(1) Download the compressed file (such as cmake-3.25.2-linux-x86_64.tar.gz), and add the bin directory to the PATH environment variable after decompression.
(2) Download the installation script (such as cmake-3.25.2-linux-x86_64.sh) and install it according to the instructions.
(3) Build from source code: download the source code (such as cmake-3.25.2.tar.gz), and execute the following commands in sequence after decompression:
./bootstrap
make
make install
2.3 macOS
Download the image file (such as cmake-3.25.2-macos-universal.dmg) or compressed file (such as cmake-3.25.2-macos-universal.tar.gz), copy CMake.app to the /Applications directory, and run it Follow the instructions in the "How to Install For Command Line Use" menu item to install the command line tool, as shown in the figure below.
After successful installation, you should be able to execute the cmake command on the command line:
$ cmake
Usage
cmake [options] <path-to-source>
cmake [options] <path-to-existing-build>
cmake [options] -S <path-to-source> -B <path-to-build>
Specify a source directory to (re-)generate a build system for it in the
current working directory. Specify an existing build directory to
re-generate its build system.
Run 'cmake --help' for more information.
3. Examples
Let's create a simple C++ Hello World project using CMake.
3.1 Create a working directory
First create the project root directory cmake-demo, and create a file CMakeLists.txt and a subdirectory hello in the root directory:
mkdir cmake-demo && cd cmake-demo
touch CMakeLists.txt
mkdir hello
The project root directory cmake-demo can be anywhere.
CMake declares build targets and dependencies through files called CMakeLists.txt. The content of CMakeLists.txt in the root directory is as follows:
cmake_minimum_required(VERSION 3.20)
project(cmake-demo)
set(CMAKE_CXX_STANDARD 14)
Among them, cmake_minimum_required()
the command specifies the minimum CMake version required by the project, project()
the command sets the project name, set()
the command sets the value of the CMake variable, and CMAKE_CXX_STANDARD
the variable specifies the C++ standard version.
3.2 Implement hello library
Create two files hello.h and hello.cpp in the hello directory, the contents are as follows:
hello.h
#pragma once
#include <string>
void hello(const std::string& to);
hello.cpp
#include "hello.h"
#include <iostream>
void hello(const std::string& to) {
std::cout << "Hello, " << to << "!\n";
}
These two files constitute a function library hello.
Create another CMakeLists.txt file in the hello directory and declare the hello library in it:
add_library(hello hello.cpp)
target_include_directories(hello INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
Among them, add_library()
the command adds a function library build target named "hello" and the source file is hello.cpp; target_include_directories()
the command indicates that all build targets linked to the hello library need to add the current source code directory (ie cmake-demo/hello) to the header file include directory and thus can be directly #include "hello.h"
.
Then add at the end of CMakeLists.txt in the project root directory:
add_subdirectory(hello)
This includes the build targets in the subdirectory hello.
3.3 Implement the hello_world program
Create a hello_world program below, main()
and call the function provided by the hello library in the function to print information.
Create a source file in the project root directory hello_world.cpp
with the following content:
#include "hello.h"
int main() {
hello("world");
return 0;
}
Add at the end of CMakeLists.txt in the project root directory:
add_executable(hello_world hello_world.cpp)
target_link_libraries(hello_world hello)
Among them, add_executable()
the command adds an executable program build target named "hello_world" and the source file is hello_world.cpp; target_link_libraries()
the command declares the dependencies between build targets : hello_world depends on hello, that is, the hello_world program needs to be linked to the hello library.
3.4 Build and run
To build the hello_world program, execute the following command in the project root directory:
$ cmake -S . -B cmake-build
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 7.5.0
...
-- Build files have been written to: .../cmake-demo/cmake-build
$ cmake --build cmake-build
[ 25%] Building CXX object hello/CMakeFiles/hello.dir/hello.cpp.o
[ 50%] Linking CXX static library libhello.a
[ 50%] Built target hello
[ 75%] Building CXX object CMakeFiles/hello_world.dir/hello_world.cpp.o
[100%] Linking CXX executable hello_world
[100%] Built target hello_world
Among them, the first step is to configure CMake, and the second step is to generate build targets. After the build is complete, the executable program hello_world will be generated in the cmake-build directory, just execute it directly:
$ cmake-build/hello_world
Hello, world!
The complete project directory structure is as follows:
cmake-demo/
CMakeLists.txt
hello_world.cpp
hello/
CMakeLists.txt
hello.h
hello.cpp
cmake-build/ # CMake自动创建
...
hello_world # 可执行程序
hello/
...
libhello.a # hello库
4. CMake command line tool
See cmake(1)cmake
for documentation on the CMake command-line tools . Linux or macOS systems can also pass or view.cmake --help
man cmake
4.1 Configuration
Configuration (configure) refers to the build target (build target) and dependencies (dependencies) declared in CMakeLists.txt to generate a build system (buildsystem) (composed of a series of build files) for a specific underlying build tool , the underlying layer used Build tools are called generators .
The configuration command is used as follows:
cmake [<options>] -S <path-to-source> -B <path-to-build>
Common options:
-S <path-to-source>
: Specify the source code directory (source directory).-B <path-to-build>
: Specify the build directory (build/binary directory), which is used to store the build files of the underlying build tools (such as Makefile) and the output of the build target (such as library files and executable files).-D <var>=<value>
: Specifies the value of the variable. Spaces in between can be omitted:-D<var>=<value>
-G <generator-name>
: Specifies the build system generator.-A <platform-name>
: Specifies the platform name (if supported by the generator).
where, if -S
and -B
only one of the two is specified, the other defaults to the current working directory.
Reconfiguration is required when build targets or dependencies change (i.e. CMakeLists.txt files change).
Note: In real projects, the build directory is usually distinguished from the source code directory, which can be easily excluded from Git.
4.1.1 Generators
The generator is the underlying build tool used by CMake to specify which build file to generate and which compiler and linker to use with the CMake configuration command. For example:
Builder | Low-level build tools | build file | compiler and linker |
---|---|---|---|
Unix Makefiles | GNU Make | Makefile | GCC(gcc和ld) |
MinGW Makefiles | MinGW Make | Makefile | GCC(gcc.exe和ld.exe) |
Visual Studio | MSBuild | .sln和.vcxproj | MSVC (cl.exe and link.exe) |
CMake supports multiple generators on different platforms, see cmake-generators(7) for details . -G
The generator to use can be specified through the options of the configure command , if not specified, the default generator for the current platform will be used. The generators and default generators supported by CMake on the current platform can cmake --help
be viewed through the command.
For example, on a Linux system you can use the Unix Makefiles generator:
cmake -G "Unix Makefiles" -S . -B cmake-build
The Visual Studio generator can be used on Windows systems (the corresponding version of Visual Studio needs to be installed):
cmake -G "Visual Studio 17 2022" -A x64 -B cmake-build
4.2 Build
Once configured, build targets can be generated based on the build system.
The usage of the build command is as follows:
cmake --build <dir> [<options>]
The build targets will be output to the corresponding subdirectories in the build directory. If only the source code changes and the CMakeLists.txt file does not change, you only need to rebuild, no reconfiguration is required.
Common options:
--build <dir>
: Specifies the project build directory.-j <jobs>
,--parallel <jobs>
: Specifies the maximum number of concurrent processes used by the build.-t <name>
,--target <name>
: Build only the specified target and its upstream dependencies. Multiple targets can be specified, separated by spaces. Builds all targets if not specified. The targetclean
is used to clean build output.--config <cfg>
: For multi-configuration build tools, specify the configuration to use, such as Debug or Release.--clean-first
: First clean the build output (i.e. the build targetclean
). If you want to clean only the build output, use--target clean
.
4.3 Installation
After the build is complete, you can install the library files and executable files in the specified build directory to the specified location, and use the install()
command to specify the installation rules.
The usage of the installation command is as follows:
cmake --install <dir> [<options>]
Common options:
--install <dir>
: Specifies the project build directory.--prefix <dir>
: Override the default installation directory prefixCMAKE_INSTALL_PREFIX
4.4 Running scripts
CMake script files are composed of CMake commands, and the suffix is usually .cmake (essentially no difference from CMakeLists.txt). usage:
cmake [-D <var>=<value>]... -P <cmake-script-file> [<args>...]
Subsequent arguments will be passed to the script, accessible through variables CMAKE_ARGC
and CMAKE_ARGV<n>
.
Note: CMAKE_ARGV0
It is the cmake executable program, CMAKE_ARGV1
yes -P
, CMAKE_ARGV2
it is the script file name, CMAKE_ARGV3
and the parameters passed to the script after that.
4.5 Running command-line tools
CMake provides some command line tools, including file and directory operations, access to environment variables, etc., which can avoid writing different script commands for different operating systems. usage:
cmake -E <command> [<options>]
Running it directly cmake -E
will list all commands.
Common commands:
cat <files>...
: Concatenate files and print to stdout.chdir <dir> <cmd> [<args>...]
: Switch the current working directory and run the command.compare_files [--ignore-eol] <file1> <file2>
: Compares two files and returns 0 if the files are the same, otherwise returns 1.--ignore-eol
Indicates the difference (LF/CRLF) that ignores newlines.copy <file>... <dst>
,copy -t <dst> <file>...
: Copy the file to the specified directory, wildcards are not supported.copy_directory <dir>... <dst>
: Copy the directory to the specified directory.echo [<args>...]
: print parameters.make_directory <dir>...
: Creates a directory and, if necessary, a parent directory.rename <oldname> <newname>
: Rename a file or directory.rm [-r] <file|dir>...
: Delete a file or directory.'r
option to delete a directory and its subdirectories recursively.
5. CMake commands
The CMakeLists.txt file itself is also a language called "CMake language". See cmake-language(7) for syntax description .
The core of the CMake language is commands , which are used to declare build targets and dependencies, specify compilation and link options, set the value of CMake variables, and more. See cmake-commands(7) for a complete list .
The syntax format of the CMake command is as follows:
command_name(arg1 arg2 ...)
command_name(KEYWORD1 arg1 KEYWORD2 arg2 ...)
Below are some commonly used CMake commands (some commands do not list all parameters).
5.1 Script commands
cmake_minimum_required
Specifies the minimum CMake version required by the project.
cmake_minimum_required(VERSION <min>)
set
Set the value of a CMake variable.
set(<variable> <value>...)
${var}
Variables can be referenced by . If multiple values are specified, the actual value of the variable is a semicolon-separated list. For example:
set(srcs a.c b.c c.c) # sets "srcs" to "a.c;b.c;c.c"
option
-D
Defines a boolean option that can be specified with an option value of ON
or in configure commands OFF
.
option(<variable> "<help_text>" [value])
Defaults to an initial value if not specified OFF
.
message
Output log messages.
message("message text" ...)
include
Load and run CMake commands from the specified file or module.
include(<file|module>)
if
A conditional statement, which executes a set of commands when a condition is true.
if(<condition>)
<commands>
elseif(<condition>) # optional block, can be repeated
<commands>
else() # optional block
<commands>
endif()
Among them, if()
the supported expression syntax and logical operators are shown in if - Condition Syntax . For example:
if(WIN32)
set(output_file NUL)
else()
set(output_file /dev/null)
endif()
while
A loop statement that repeatedly executes a set of commands while a condition is true.
while(<condition>)
<commands>
endwhile()
foreach
A loop statement that executes a set of commands for each value in a list.
foreach(<loop_var> <items>)
<commands>
endforeach()
There are several variants of this command:
(1) Traversing integers
foreach(<loop_var> RANGE <stop>)
foreach(<loop_var> RANGE <start> <stop> [<step>])
Traverse the integers between 0 ~ stop
or start
~ , including the upper bound . Among them, , and must be non-negative integers, and greater than or equal to , the default is 1.stop
start
stop
step
stop
start
step
For example:
foreach(i RANGE 1 3)
add_executable(prog${i} prog${i}.cpp)
endforeach()
Equivalent to
add_executable(prog1 prog1.cpp)
add_executable(prog2 prog2.cpp)
add_executable(prog3 prog3.cpp)
(2) traverse the list
foreach(<loop_var> IN ITEMS <items>)
where items
is a semicolon separated list.
For example:
foreach(i IN ITEMS foo;bar;baz)
add_executable(${i} ${i}.cpp)
endforeach()
Equivalent to
add_executable(foo foo.cpp)
add_executable(bar bar.cpp)
add_executable(baz baz.cpp)
break
Jump out foreach()
or while()
loop.
break()
continue
Continue to next time foreach()
or while()
cycle.
continue()
function
Define the function.
function(<name> [<arg1> ...])
<commands>
endfunction()
This command defines a function named , which can accept parameters, and reference parameters name
can be used in the function body . The commands in the function body will only be executed when the function is called.${arg1}
arg1
For example:
function(add_gui_executable name source)
add_executable(${name} ${source})
target_link_libraries(${name} GUI)
endfunction()
add_gui_executable(foo foo.cpp)
add_gui_executable(bar bar.cpp)
Equivalent to
add_executable(foo foo.cpp)
target_link_libraries(foo GUI)
add_executable(bar bar.cpp)
target_link_libraries(bar GUI)
In the function body, in addition to ${arg1}
other formal parameters, the following variables can also be used:
ARGC
: the number of actual parametersARGV0
,ARGV1
,ARGV2
etc.: the value of each actual parameterARGV
: list of all parametersARGN
: list of all arguments after the last expected argument
These variables can be used to create functions with optional parameters. For example, the function defined above add_gui_executable()
can only accept a single source file argument source
. To accept multiple source files can be modified to:
function(add_gui_executable name)
add_executable(${name} ${GUI_TYPE} ${ARGN})
target_link_libraries(${name} GUI)
endfunction()
add_gui_executable(foo foo.cpp bar.cpp)
Note: function()
Commands only support positional parameters, and cmake_parse_arguments()
commands can be used to implement keyword parameters.
cmake_parse_arguments
Parse function arguments.
cmake_parse_arguments(<prefix> <option_keywords> <one_value_keywords> <multi_value_keywords> <args>...)
Among them, option_keywords
specifying all option keywords (that is, keyword arguments without a value), one_value_keywords
specifying all single-value keywords, and multi_value_keywords
specifying all multi-value keywords <args>...
are the parameters to be processed. The parsing results will be saved in the variables corresponding to each keyword, and the naming format is <prefix>_<keyword>
.
For example:
function(my_install)
set(option_keywords OPTIONAL FAST)
set(one_value_keywords DESTINATION RENAME)
set(multi_value_keywords TARGETS CONFIGURATIONS)
cmake_parse_arguments(MY_INSTALL "${option_keywords}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN})
# ...
endfunction()
If called like this my_install()
:
my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)
Then the following variables will be defined after calling in the function body cmake_parse_arguments()
:
MY_INSTALL_OPTIONAL = TRUE
MY_INSTALL_FAST = FALSE # was not used in call to my_install
MY_INSTALL_DESTINATION = "bin"
MY_INSTALL_RENAME <UNDEFINED> # was not used
MY_INSTALL_TARGETS = "foo;bar"
MY_INSTALL_CONFIGURATIONS <UNDEFINED> # was not used
MY_INSTALL_UNPARSED_ARGUMENTS = "blub" # nothing expected after "OPTIONAL"
MY_INSTALL_KEYWORDS_MISSING_VALUES = "CONFIGURATIONS"
list
For list operations, see list for details .
string
For string operations, see string for details .
file
For file operations, see file for details .
execute_process
Execute one or more child processes.
execute_process(
COMMAND <cmd1> [<args>]
[COMMAND <cmd2> [<aegs>]]...
[WORKING_DIRECTORY <directory>]
[RESULT_VARIABLE <variable>]
[OUTPUT_VARIABLE <variable>]
[ERROR_VARIABLE <variable>]
[INPUT_FILE <file>]
[OUTPUT_FILE <file>]
[ERROR_FILE <file>]
[COMMAND_ERROR_IS_FATAL <ANY|LAST>])
Commands are executed concurrently in the form of pipelines, and the standard output of each command is connected to the standard input of the next command through the pipeline.
execute_process()
is to run the specified command at CMake configure timeadd_custom_command()
, use to create a custom command to run at build time.
options:
COMMAND
: subprocess command line. Redirection operators (for example>
) are treated as normal arguments, using theINPUT*
,OUTPUT*
andERROR*
options to redirect stdin, stdout, and stderr.WORKING_DIRECTORY
: The working directory for executing the command.RESULT_VARIABLE
: The specified variable will be set to the result (return code or error message) of the last subprocess.OUTPUT_VARIABLE
,ERROR_VARIABLE
: The specified variable will be set to the contents of standard output and standard error, respectively.INPUT_FILE
: Redirect the standard input of the first child process to the specified file.OUTPUT_FILE
: Redirect the standard output of the last child process to the specified file.ERROR_FILE
: Redirect the standard error of all child processes to the specified file.COMMAND_ERROR_IS_FATAL
:ANY
Indicates that any command failure is considered a failure,LAST
and that only the last command fails is considered a failure.
5.2 Project commands
project
Set the project name.
project(<name>)
This command will set the following variables:
PROJECT_NAME
:project namePROJECT_SOURCE_DIR
: project source code directoryPROJECT_BINARY_DIR
: project build directory
add_subdirectory
Add the specified subdirectory to the build.
add_subdirectory(<dir>)
If dir
it is a relative path, it is relative to the current directory. CMake will immediately process the CMakeLists.txt file in the subdirectory when executing this command.
add_executable
Add an executable build target.
add_executable(<name> <source>...)
The executable file name is <name>
(Linux) or <name>.exe
(Windows).
add_library
Add library build target.
add_library(<name> [STATIC|SHARED] <source>...)
The type of library file can be specified:
STATIC
: Static link library (default), library file namelib<name>.a
(Linux) or<name>.lib
(Windows)SHARED
: Dynamic link library, the library file name islib<name>.so
(Linux) or<name>.dll
(Windows)
add_test
Add tests, see Section 7 for details.
target_include_directories
Add include directories for the given target (equivalent to GCC compiler -I
options).
target_include_directories(<target> <PUBLIC|INTERFACE|PRIVATE> <dir>...)
Among them, PUBLIC
, INTERFACE
and PRIVATE
keywords are used to specify the scope of the option:
PUBLIC
: takes effect on both the target and its downstream dependenciesINTERFACE
: Only the downstream dependencies of this target take effectPRIVATE
: Only valid for this target
Relative paths will be interpreted relative to the current source code directory.
For example:
add_library(foo foo.cpp)
target_include_directories(foo INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
A function library foo is defined, and the downstream dependency of foo is specified to add the current source code directory to the include directory, so that the header files in the current directory can be directly included.
target_link_directories
Add library directories for the given target (equivalent to GCC compiler -L
options).
target_link_directories(<target> <PUBLIC|INTERFACE|PRIVATE> <dir>...)
Note: Generally, you don’t need to use this command, target_link_libraries()
just use it directly.
target_link_libraries
Add dependent libraries, i.e. upstream dependencies (equivalent to GCC compiler -l
options) for a given target. Dependent libraries are involved in linking when building an executable.
target_link_libraries(<target> <PUBLIC|INTERFACE|PRIVATE> <item>...)
target_link_libraries(<target> <item>...)
Among them, the second form is equivalent PUBLIC
to adding a dependent library for a given target and its downstream dependencies, so that the dependencies are transitive.
Each <item>
can be:
- library target name,
add_library()
created by - The full path to the library file
- library file name (e.g.
foo
becomes-lfoo
orfoo.lib
) - Link options,
-
starting with but-l
and-framework
excluding .
For example:
add_library(foo foo.cpp)
add_library(bar bar.cpp)
add_library(baz baz.cpp)
target_link_libraries(bar foo)
target_link_libraries(baz INTERFACE foo)
Three libraries foo, bar and baz are defined, bar and its downstream dependencies all depend on foo, baz's downstream dependencies all depend on foo, but baz itself does not depend on foo.
target_compile_options
Add compile options for the given target.
target_compile_options(<target> <PUBLIC|INTERFACE|PRIVATE> <item>...)
target_compile_definitions
-D
Add macro definitions (equivalent to GCC compiler options) for the given target .
target_compile_definitions(<target> <PUBLIC|INTERFACE|PRIVATE> <item>...)
where <item>
the format is name=definition
or name
. For example:
target_compile_definitions(foo PUBLIC FOO)
target_compile_definitions(foo PUBLIC FOO=bar)
target_link_options
Add link options for the given target.
target_link_options(<target> <PUBLIC|INTERFACE|PRIVATE> <item>...)
include_directories
Add include directories for all targets in the current directory and subdirectories.
include_directories(<dir>...)
Note: Priority is used target_include_directories()
.
link_directories
Add library directories for all targets in the current directory and subdirectories.
link_directories(<dir>...)
Note: Priority is used target_link_directories()
.
link_libraries
Add dependent libraries for all targets in the current directory and subdirectories.
link_libraries(<item>...)
Note: Priority is used target_link_libraries()
.
add_compile_options
Add compile options for all targets in the current directory and subdirectories.
add_compile_options(<option>...)
Note: Priority is used target_compile_options()
.
add_compile_definitions
Add macro definitions for all targets in the current directory and subdirectories.
add_compile_definitions(<definition>...)
Note: Priority is used target_compile_definitions()
.
add_link_options
Add link options for all targets in the current directory and subdirectories.
add_link_options(<option>...)
Note: Priority is used target_link_options()
.
add_custom_command
Add custom build rules.
add_custom_command(
OUTPUT output...
COMMAND command [ARGS] [args...]
DEPENDS depends...
[WORKING_DIRECTORY dir]
[VERBATIM])
where, depends
can be a build target or a filename, and VERBATIM
the option ensures that the arguments to the command are properly escaped. If command
it is an executable target, it will be automatically replaced with the path to the executable generated by the build.
For example:
add_custom_command(
OUTPUT out.c
COMMAND someTool -i ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
-o out.c
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
VERBATIM)
add_library(myLib out.c)
Command arguments can contain redirection operators (eg >
.
add_custom_target
Add a custom target with no output.
add_custom_target(
name
[COMMAND command [args...] ...]
[DEPENDS depends... ]
[WORKING_DIRECTORY dir]
[VERBATIM]
[SOURCES src1 [src2...]])
install
Specifies the installation rules.
install(TARGETS targets... DESTINATION <dir>)
install(FILES files... DESTINATION <dir>)
The first form is used to install a build target (library or executable), which dir
can be an absolute path or a relative path, and a relative path will be interpreted as relative to CMAKE_INSTALL_PREFIX
the value of the variable.
The second form is used to install files, relative to the current source code directory if the filename is a relative path.
For example:
add_executable(foo foo.cpp)
add_library(bar bar.cpp)
install(TARGETS foo DESTINATION bin)
install(TARGETS bar DESTINATION lib)
install(FILES bar.h DESTINATION include)
When executing the installation command, cmake --install
install the executable file foo, library file libbar.a, and header file bar.h to the CMAKE_INSTALL_PREFIX
bin, lib, and include directories below.
5.3 Generator expressions
cmake-generator-expressions(7)
6. CMake built-in variables
CMake provides many built-in variables, which can be specified through set()
commands or -D
options. The following are some commonly used variables, see cmake-variables(7) for a complete list .
6.1 Path related variables
CMAKE_COMMAND
: full path to the cmake commandCMAKE_GENERATOR
: The generator used to build the projectCMAKE_SOURCE_DIR
: top-level source code directoryCMAKE_BINARY_DIR
: top-level build directoryCMAKE_CURRENT_SOURCE_DIR
: current source code directoryCMAKE_CURRENT_BINARY_DIR
: current build directoryPROJECT_NAME
:project()
name of the project that most recently invoked the commandPROJECT_SOURCE_DIR
:project()
The project source code directory where the command was most recently invokedPROJECT_BINARY_DIR
:project()
The project build directory where the command was most recently invoked
6.2 System related variables
LINUX
: If the target system is Linux, set it toTRUE
WIN32
: If the target system is Windows then set toTRUE
APPLE
: If the target system is macOS set toTRUE
6.3 Language-dependent variables
CMAKE_C_STANDARD
: The default C standard version, the optional values are 90, 99, 11, 17, 23, etc.CMAKE_CXX_STANDARD
: The default C++ standard version, the optional values are 98, 11, 14, 17, 20, 23, 26, etc.CMAKE_<LANG>_COMPILER
: The full path of the compiler of the specified language,<LANG>
which can be C, CXX, etc.CMAKE_<LANG>_FLAGS
: Compilation options for the specified language
6.4 Build/install related variables
CMAKE_BUILD_TYPE
: Specify the build type of a single-configuration generator (such as Makefile, Ninja, etc.), such asDebug
,Release
etc., see Build Configurations for details .CMAKE_INSTALL_PREFIX
:install()
The installation directory to use. Defaults to "/usr/local" on UNIX and "C:\Program Files/${PROJECT_NAME}" on Windows.
7. Test
CMake provides testing support through the CTest module.
First call the command in CMakeLists.txt in the project root directory , and then you can add tests enable_testing()
through commands in any CMakeLists.txt .add_test()
7.1 Adding tests
add_test()
The usage of the command is as follows:
add_test(
NAME <name>
COMMAND <command> [<arg>...]
[WORKING_DIRECTORY <dir>])
Among them, command
the specified test command, if it is an executable file target, will be automatically replaced with the path of the executable file generated by the build. If the return code of the command is 0, the test is considered to pass, otherwise the test fails.
Note: Since CTest
the test command is not executed in the shell, standard input/output redirection cannot be used, and command
the <
and >
will be treated as ordinary parameters. If you need to redirect the standard input/output of the test command, there are two ways:
- Use
bash -c
, for exampleadd_test(NAME my_test COMMAND sh -c "foo < in.txt > out.txt")
, but this method is not platform independent and needs to be used on Windowscmd /c
. execute_process()
Invoke the actual test command in a cmake script , and call that scriptadd_test()
in .cmake -P
reference:
7.2 Running the tests
The command line tool for running tests is ctest(1)ctest
for documentation .
After adding tests and configuring and building, just execute the command directly in the build directoryctest
.
Note: CTest itself does not provide any assertion or comparison functions, how to execute the test is completely determined by the test command.
7.3 GoogleTest
GoogleTest is a commonly used C++ testing framework, and CMake provides support for GoogleTest through the GoogleTest module.
For an example, see the GoogleTest tutorial .
8. Module
CMake comes with some modules that provide additional functions , such as the aforementioned CTest
and GoogleTest
can include()
be loaded by commands. See cmake-modules(7) for a complete list .
8.1 FetchContent
The FetchContent module provides the function of automatically loading external items at configuration time, the main commands are FetchContent_Declare()
and FetchContent_MakeAvailable()
.
Example:
- GoogleTest: Section 3.2 of the GoogleTest tutorial
- FLTK: "C++ Programming Principles and Practice" Notes Chapter 12 A Display Model Section 12.8.2
- gRPC: Section 2.1.3 of the gRPC Getting Started Tutorial