Getting Started
Installing CMake
Running CMake
Building a project
~/package $ mkdir build
~/package $ cd build
~/package/build $ cmake ..
~/package/build $ make
make 可以替换成 cmake --build .
新版本的 cmake 可以使用-S, -B 指定 source 和 build 目录:
~/package $ cmake -S . -B build
~/package $ cmake --build build
install 命令:
# From the build directory (pick one)
~/package/build $ make install
~/package/build $ cmake --build . --target install
~/package/build $ cmake --install . # CMake 3.15+ only
# From the source directory (pick one)
~/package $ make -C build install
~/package $ cmake --build build --target install
~/package $ cmake --install build # CMake 3.15+ only
Picking a compiler
Selecting a compiler must be done on the first run in an empty directory.
CC=clang CXX=clang++ cmake ..
Picking a generator
通过cmake -G
选项,或者CMAKE_GENERATOR
环境变量来选择。
Setting options
cmake -D
: 设置 variables。
cmake -L
, cmake -LH
: 查看 variables。
Verbose and partial builds
Although not all build tools support it, you can get verbose builds (pick one):
cmake --build build --verbose
VERBOSE=1 make
Standard options
一些常用的 cmake 变量:
-DCMAKE_BUILD_TYPE
: pick from Release/RelWithDebInfo/Debug…
-DCMAKE_INSTALL_PREFIX
: install 目录,unix system install 默认的是 usr/local,
user install 默认的是~/.local
-DBUILD_SHARED_LIBS
: ON/OFF, 设置默认编译库的方式。
_DBUILD_TESTING
:
Debugging your CMake files
前面 verbose build 是查看 build 时的信息,如果想要查看 cmake configure 时的信息,
--trace
选项会打印出 CMake 运行的每一行。--trace-source="filename"
会有选择的打印某个
文件的 configure 信息。
Do’s and Don’ts
CMake Antipatterns
- 不要使用全局函数,例如
link_directories
,include_libraries
… - 不要过度使用 PUBLIC.
- 不要 GLOB files.
- Link to built files directly.
- linking 的时候不要跳过 PUBILIC/PRIVATE.
CMake Patterns
The basics
Introduction to the basics
最简单的 cmake:
cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0
DESCRIPTION "Very nice project"
LANGUAGES CXX)
add_executable(one two.cpp three.h)
添加 library:
add_library(one STATIC two.cpp three.h)
可以选择的 type 有 STATIC/SHARED/MODULE. 如果不选择,那么由 BUILD_SHARED_LIBS 选择, 默认的是 STATIC.
给 target 增加 include 目录:
target_include_directories(one PUBLIC include)
对于 executable, PUBLIC 关键字没什么意义。
对于 library 来说, PUBLIC lets CMake know that any targets that link to this target must also need that include directory。
PRIVATE 只影响当前 target include directory, 不影响其他依赖于当前 target 的 targets, 相当于其他 targets 不能使用定义的 include directory.
INTERFACE 只影响依赖于当前 target 的 targets, 相当于当前 target 不使用定义的 include directory, 而其他 targets 可以使用.
把 targets 链接起来:
add_library(another STATIC another.cpp another.h)
target_link_libraries(another PUBLIC one)
// TODO:
target_link_libraries 中的PUBLIC表示,后面 another 库,和后面依赖于 another 的库可以使用 one 库.
如果 target one 不存在,
Variables and the Cache
Local Variables
设置变量:
set(MY_VARIABLE "value")
设置 list:
set(MY_LIST "one" "two")
set(MY_LIST "one;two") # 和上面效果一样
在 cmake 中如果一个变量中间不带空格,那么带引号和不带引号是一样的.
但如果带了空格,那么就需要加上引号,比如需要使用"${PATH}"
而不是${PATH}
普通变量只在当前 CMakeLists.txt 中生效,不能跨越文件.
Cache Variables
设置一个之前没设置过的 cache variable:
set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "Description")
不会代替已经存在的变量, 缓存变量的作用是使得可以通过 command line 来设置这些变量,并且不会在 cmake file 执行的过程中被覆盖.
把变量作为一个临时的全局变量:
set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "" FORCE)
mark_as_advanced(MY_CACHE_VARIABLE)
也可以通过 INTERNAL 来达到相同的目的:
set(MY_CACHE_VARIABLE "VALUE" CACHE INTERNAL "")
设置 bool 类型的 cache variable,有一个 shortcut:
option(MY_OPTION "This is settable from the command line" OFF)
Environment Variables
set: set(ENV{variable_name} value)
get: $ENV{variable_name}
The Cache
Cache 变量都保存在 CMakeCache.txt, 这样每次 rerun CMake 不用重新设置变量.
Properties
properties 相当于是依附在 directory or target 上的一个属性. 许多 target properties 都是以
CMAKE_开头,比如CMAKE_CXX_STANDARD
.
设置 property:
set_property(TARGET TargetName PROPERTY CXX_STANDARD 11)
set_target_properties(TargetName PROPERTIES CXX_STANDARD 11) # shortcut
获取 property:
get_property(ResultVariable TARGET TargetName PROPERTY CXX_STANDARD)
Programming in CMake
Control flow
if 语句:
if("${variable}")
# True if variable is not false-like
else()
# Note that undefined variables would be `""` thus false
endif()
CMake 不会再展开已经被引号括起来的展开变量。
generator-expressions
Macros and Functions
marco 和 function 的区别是作用域, function 中的变量在外部不可见,如果要外部可见需要加上PARENT_SCOPE
关键字, 并且如果是嵌套函数中每个相同的变量都要加上.
function(SIMPLE REQUIRED_ARG)
message(STATUS "Simple arguments: ${REQUIRED_ARG}, followed by ${ARGN}")
set(${REQUIRED_ARG} "From SIMPLE" PARENT_SCOPE)
endfunction()
simple(This Foo Bar)
message("Output: ${This}")
Output:
-- Simple arguments: This, followed by Foo;Bar
Output: From SIMPLE
Arguments
cmake_parse_arguments
Communication with your code
Configure file
cmake 允许通过 configure file 访问 cmake 变量.
// TODO:
Reading files
// TODO: