CMake build tool tutorial

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.

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.

Visual Studio Installer

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.

macOS CMake

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_STANDARDthe 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.cppwith 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 --helpman 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 -Sand -Bonly 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 . -GThe 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 --helpbe 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 target cleanis 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 target clean). 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_ARGCand CMAKE_ARGV<n>.

Note: CMAKE_ARGV0It is the cmake executable program, CMAKE_ARGV1yes -P, CMAKE_ARGV2it is the script file name, CMAKE_ARGV3and 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 -Ewill 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-eolIndicates 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. 'roption 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

-DDefines a boolean option that can be specified with an option value of ONor 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 ~ stopor start~ , including the upper bound . Among them, , and must be non-negative integers, and greater than or equal to , the default is 1.stopstartstopstepstopstartstep

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 itemsis 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 namecan 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 parameters
  • ARGV0, ARGV1, ARGV2etc.: the value of each actual parameter
  • ARGV: list of all parameters
  • ARGN: 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_keywordsspecifying all option keywords (that is, keyword arguments without a value), one_value_keywordsspecifying all single-value keywords, and multi_value_keywordsspecifying 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 the INPUT*, OUTPUT*and ERROR*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: ANYIndicates that any command failure is considered a failure, LASTand 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 name
  • PROJECT_SOURCE_DIR: project source code directory
  • PROJECT_BINARY_DIR: project build directory

add_subdirectory

Add the specified subdirectory to the build.

add_subdirectory(<dir>)

If dirit 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 name lib<name>.a(Linux) or <name>.lib(Windows)
  • SHARED: Dynamic link library, the library file name is lib<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 -Ioptions).

target_include_directories(<target> <PUBLIC|INTERFACE|PRIVATE> <dir>...)

Among them, PUBLIC, INTERFACEand PRIVATEkeywords are used to specify the scope of the option:

  • PUBLIC: takes effect on both the target and its downstream dependencies
  • INTERFACE: Only the downstream dependencies of this target take effect
  • PRIVATE: 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 -Loptions).

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 -loptions) 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 PUBLICto 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. foobecomes -lfooor foo.lib)
  • Link options, -starting with but -land -frameworkexcluding .

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

-DAdd 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=definitionor 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, dependscan be a build target or a filename, and VERBATIMthe option ensures that the arguments to the command are properly escaped. If commandit 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 dircan be an absolute path or a relative path, and a relative path will be interpreted as relative to CMAKE_INSTALL_PREFIXthe 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 --installinstall the executable file foo, library file libbar.a, and header file bar.h to the CMAKE_INSTALL_PREFIXbin, 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 -Doptions. 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 command
  • CMAKE_GENERATOR: The generator used to build the project
  • CMAKE_SOURCE_DIR: top-level source code directory
  • CMAKE_BINARY_DIR: top-level build directory
  • CMAKE_CURRENT_SOURCE_DIR: current source code directory
  • CMAKE_CURRENT_BINARY_DIR: current build directory
  • PROJECT_NAME: project()name of the project that most recently invoked the command
  • PROJECT_SOURCE_DIR: project()The project source code directory where the command was most recently invoked
  • PROJECT_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 as Debug, Releaseetc., 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, commandthe 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 CTestthe test command is not executed in the shell, standard input/output redirection cannot be used, and commandthe <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 example add_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 Windows cmd /c.
  • execute_process()Invoke the actual test command in a cmake script , and call that script add_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 CTestand GoogleTestcan 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:

Guess you like

Origin blog.csdn.net/zzy979481894/article/details/129109513