CMakeLists¶
- https://cmake.org/cmake/help/latest/
- https://runebook.dev/zh-CN/docs/cmake/
- https://zhuanlan.zhihu.com/p/534439206
CMakeLists中命令不区分大小写的,但通常建议命令使用大写
1 入门示例¶
cmake_minimum_required
:指定cmake最低版本project
:指定项目名称add_executable
:添加可执行文件
cmake_minimum_required(VERSION 3.10)
## set the project name
project(Tutorial)
## add the executable
add_executable(Tutorial tutorial.cxx)
2 项目命令¶
2.1 项目设置¶
2.1.1 cmake_minimum_required¶
- 功能:设置需要的cmake最小版本号
- 语法:
cmake_minimum_required(VERSION <min>[...<policy_max>] [FATAL_ERROR])
<min>
:(必选)最小版本号,格式是major.minor[.patch[.tweak]]
,比如1.2.0...<policy_max>
:(可选)最大版本号FATAL_ERROR
:(可选)该参数在cmake的_2.6_及以后的版本被忽略,在cmake的_2.4_及以前的版本,需要指明该参数,以便cmake能提示失败而不仅仅是一个警告。
- 示例
cmake_minimum_required(VERSION 3.12.0)
cmake_minimum_required(VERSION 3.12.0...3.24.0)
2.1.2 project¶
project会影响以下几个变量:
- `PROJECT_NAME`:这是在当前目录范围或上层范围内最近一次调用的 project() 命令的名称。
- `CMAKE_PROJECT_NAME`:这是在顶级 CMakeLists.txt 文件中最近一次调用project() 命令的名称。
- `PROJECT_SOURCE_DIR`, `<PROJECT-NAME>_SOURCE_DIR`:项目源文件的绝对路径
- `PROJECT_BINARY_DIR`, `<PROJECT-NAME>_BINARY_DIR`:项目二进制文件的绝对路径
- `PROJECT_IS_TOP_LEVEL`, `<PROJECT-NAME>_IS_TOP_LEVEL`:New in version 3.21.
- 功能:设置项目的名称,并将其存储在变量 PROJECT_NAME 中。当从顶层调用时,CMakeLists.txt 还将项目名称存储在变量 CMAKE_PROJECT_NAME 中。
- 语法:
project(<PROJECT-NAME> [<language-name>...])
- 示例
cmake_minimum_required(VERSION 3.0)
project(First)
project(Second)
add_subdirectory(sub)
project(Third)
2.2 库生成¶
1. `add_dependencies`相当于gcc中`-l`链接库
2. `target_include_directories、include_directories`相当于gcc中`-I`头文件搜索路径
3.
2.2.1 add_executable¶
- 功能:使用指定的源文件生成可执行文件。
- 语法:
add_executable(<name> [source1] [source2 ...])
<name>
:可执行文件名[source1] [source2 ...]
:源文件名
- 示例
add_executable(main main.cc)
2.2.2 add_library¶
- 功能:使用指定的源文件生成库文件。
- 语法:
add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [<source>...])
<name>
[STATIC | SHARED | MODULE]
:STATIC表示静态库、SHARED表示动态库[EXCLUDE_FROM_ALL]
[<source>...]
title: 当不指定库类型时,生成静态库还是动态库,遵循什么规则?
1. 当`BUILD_SHARED_LIBS`变量值为ON时,生成动态库,否则生成静态库
- 示例:设置BUILD_SHARED_LIBS变量值ON,生成动态库
message(STATUS "BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}" )
set(BUILD_SHARED_LIBS on )
message(STATUS "BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}" )
add_library(MathFunctions mysqrt.cxx)
## cmake输出结果(部分)
-- BUILD_SHARED_LIBS=
-- BUILD_SHARED_LIBS=on
## make 输出结果(部分)
[ 25%] Building CXX object MathFunctions/CMakeFiles/MathFunctions.dir/mysqrt.cxx.o
[ 50%] Linking CXX shared library libMathFunctions.so
- 示例:生成动态库
add_library(MathFunctions SHARED mysqrt.cxx)
### make 输出结果(部分)
[ 25%] Building CXX object MathFunctions/CMakeFiles/MathFunctions.dir/mysqrt.cxx.o
[ 50%] Linking CXX shared library libMathFunctions.so
- 示例:生成静态库
add_library(MathFunctions STATIC mysqrt.cxx)
### make 输出结果(部分)
[ 25%] Building CXX object MathFunctions/CMakeFiles/MathFunctions.dir/mysqrt.cxx.o
[ 50%] Linking CXX static library libMathFunctions.a
2.2.3 add_dependencies¶
- 功能:在目标添加一个依赖关系,确保依赖库在目标链接前已经存在,比如生成main可执行文件需要链接liba.so,libb.so,则可以使用
add_dependencies(main a b)
- 语法:
add_dependencies(<target> [<target-dependency>]...)
<target>
:只能是add_library、add_executable
指定的目标文件
2.2.4 add_definitions¶
- 功能:添加宏定义
- 语法
add_definitions(-DFOO -DBAR ...)
2.2.5 add_compile_definitions¶
- 功能:将预处理器定义添加到源文件的编译中
- 语法:
add_compile_definitions(<definition> ...)
,使用语法 VAR 或 VAR=value 指定定义。
2.2.6 target_include_directories、include_directories¶
title: target_include_directories、include_directories区别?
其中target_include_directories只添加到指定的目标上,而include_directories将给定目录添加到编译器用于搜索包含文件的目录
- 功能:添加 include 文件搜索路径
target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [items1...]
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
2.2.7 target_link_libraries¶
- 功能:指定目标文件的依赖库
- 语法:
target_link_libraries(<target> ... <item>... ...)
<target>
:只能是add_library、add_executable
指定的目标文件
2.2.8 add_subdirectory¶
- 功能:将子目录添加到 cmake 构建树中。
- 语法:
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL] [SYSTEM])
其中 source_dir
指定了源 CMakeLists.txt 和代码文件所在的目录,可选的 binary_dir
表示的是构建生成二进制文件的位置,如果不指定 binary_dir
,则使用 source_dir
作为输出目录
2.3 依赖检查¶
2.3.1 find_library¶
- 功能:找到一个库。
- 语法:
find_library (<VAR> name1 [path1 path2 ...])
其中 <VAR>
是一个变量,用来存储查询结果,如果查询成功则是库的全路径,否则是 <VAR>-NOTFOUND
。name1
是查询的库名称,可以是 libnsl.so
或者去除前缀后缀的 nsl
。path
则表示要搜索库的位置。
2.3.2 find_package¶
- 功能:找到一个包 (通常由项目外部提供)。
2.4 脚本命令¶
2.4.1 message¶
在3.17后增加了check功能
-功能:输出提示信息 - 语法:
message([<mode>] "message text" ...)
message(<checkState> "message text" ...)
- 主要的mode有
FATAL_ERROR
:错误,会停止执行cmake命令WARNING
:警告,继续执行STATUS
:状态信息
- 新增的checkState有以下:
CHECK_START
:检查记录的开始CHECK_PASS
:检查成功信息CHECK_FAIL
:检查失败信息
- 示例
message(CHECK_START "Finding my things")
list(APPEND CMAKE_MESSAGE_INDENT " ")
unset(missingComponents)
message(CHECK_START "Finding partA")
## ... do check, assume we find A
message(CHECK_PASS "found")
message(CHECK_START "Finding partB")
## ... do check, assume we don't find B
list(APPEND missingComponents B)
message(CHECK_FAIL "not found")
list(POP_BACK CMAKE_MESSAGE_INDENT)
if(missingComponents)
message(CHECK_FAIL "missing components: ${missingComponents}")
else()
message(CHECK_PASS "all components found")
endif()
- 输出
-- Finding my things
-- Finding partA
-- Finding partA - found
-- Finding partB
-- Finding partB - not found
-- Finding my things - missing components: B
2.4.2 set¶
- 功能:给变量设置值
- 语法:
- 设置普通变量:
set(<variable> <value>... [PARENT_SCOPE])
- 设置Cache Entry:
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
- 设置ENV变量:
set(ENV{<variable>} [<value>])
- 设置普通变量:
- 示例
message(STATUS "BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}" )
set(BUILD_SHARED_LIBS on )
message(STATUS "BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}" )
message(STATUS "CC=$ENV{CC}")
set(ENV{CC} g++)
message(STATUS "CC=$ENV{CC}")
- 输出
-- BUILD_SHARED_LIBS=
-- BUILD_SHARED_LIBS=on
-- CC=
-- CC=g++
-- Configuring done
-- Generating done
2.4.3 string¶
- 内容较多,参考[官方文档](https://cmake.org/cmake/help/latest/command/string.html#string)
- 功能:字符串操作,包括查找、替换、比较等
- 语法
Search and Replace
string(FIND <string> <substring> <out-var> [...])
string(REPLACE <match-string> <replace-string> <out-var> <input>...)
string(REGEX MATCH <match-regex> <out-var> <input>...)
string(REGEX MATCHALL <match-regex> <out-var> <input>...)
string(REGEX REPLACE <match-regex> <replace-expr> <out-var> <input>...)
Manipulation
string(APPEND <string-var> [<input>...])
string(PREPEND <string-var> [<input>...])
string(CONCAT <out-var> [<input>...])
string(JOIN <glue> <out-var> [<input>...])
string(TOLOWER <string> <out-var>)
string(TOUPPER <string> <out-var>)
string(LENGTH <string> <out-var>)
string(SUBSTRING <string> <begin> <length> <out-var>)
string(STRIP <string> <out-var>)
string(GENEX_STRIP <string> <out-var>)
string(REPEAT <string> <count> <out-var>)
Comparison
string(COMPARE <op> <string1> <string2> <out-var>)
Hashing
string(<HASH> <out-var> <input>)
Generation
string(ASCII <number>... <out-var>)
string(HEX <string> <out-var>)
string(CONFIGURE <string> <out-var> [...])
string(MAKE_C_IDENTIFIER <string> <out-var>)
string(RANDOM [<option>...] <out-var>)
string(TIMESTAMP <out-var> [<format string>] [UTC])
string(UUID <out-var> ...)
JSON
string(JSON <out-var> [ERROR_VARIABLE <error-var>]
{GET | TYPE | LENGTH | REMOVE}
<json-string> <member|index> [<member|index> ...])
string(JSON <out-var> [ERROR_VARIABLE <error-var>]
MEMBER <json-string>
[<member|index> ...] <index>)
string(JSON <out-var> [ERROR_VARIABLE <error-var>]
SET <json-string>
<member|index> [<member|index> ...] <value>)
string(JSON <out-var> [ERROR_VARIABLE <error-var>]
EQUAL <json-string1> <json-string2>)
2.4.4 list¶
- 内容较多,参考[官方文档](https://cmake.org/cmake/help/latest/command/list.html#list)
- 功能:列表操作
- 语法:其中最常用的是APPEND,向列表追加内容
Reading
list(LENGTH <list> <out-var>)
list(GET <list> <element index> [<index> ...] <out-var>)
list(JOIN <list> <glue> <out-var>)
list(SUBLIST <list> <begin> <length> <out-var>)
Search
list(FIND <list> <value> <out-var>)
Modification
list(APPEND <list> [<element>...])
list(FILTER <list> {INCLUDE | EXCLUDE} REGEX <regex>)
list(INSERT <list> <index> [<element>...])
list(POP_BACK <list> [<out-var>...])
list(POP_FRONT <list> [<out-var>...])
list(PREPEND <list> [<element>...])
list(REMOVE_ITEM <list> <value>...)
list(REMOVE_AT <list> <index>...)
list(REMOVE_DUPLICATES <list>)
list(TRANSFORM <list> <ACTION> [...])
Ordering
list(REVERSE <list>)
list(SORT <list> [...])
2.4.5 option¶
- 功能:提供用户可以选择的布尔选项。通常和if条件语句配合使用,可选择的执行命令
- 语法:
option(<variable> "<help_text>" [value])
<variable>
:选项的变量名"<help_text>"
:针对选项的帮助信息[value]
:默认是OFF,表示选项关闭,ON表示选项打开
- 示例
option(OPENMESSAGE "是否执行信息输出" OFF)
if(OPENMESSAGE)
message(STATUS "condition 1")
else()
message(STATUS "condition 2")
endif()
- 输出:cmake .
$ cmake .
-- condition 2
- 输出: cmake -DOPENMESSAGE=ON .
$ cmake -DOPENMESSAGE=ON .
-- condition 1
2.4.6 条件if¶
- 详细教程参考[官方文档](https://cmake.org/cmake/help/latest/command/if.html)
- 功能:有条件地执行一组命令。
- 语法:
if(<condition>)
<commands>
elseif(<condition>) ## optional block, can be repeated
<commands>
else() ## optional block
<commands>
endif()
- 示例
option(OPENMESSAGE "是否执行信息输出" OFF)
if(OPENMESSAGE)
message(STATUS "condition 1")
else()
message(STATUS "condition 2")
endif()
2.4.7 function¶
- 功能:定义一个函数,可以被调用。
- 语法:
function(<name> [<arg1> ...])
<commands>
endfunction()
其中 <name>
表示函数名称,<arg1>
表示函数参数,<commands>
是函数体,最后的 endfunction()
是函数结束标志。
定义为:
function(foo)
<commands>
endfunction()
函数调用不区分大小写。可以以下任一种方式调用:
foo()
Foo()
FOO()
cmake_language(CALL foo)
2.4.8 endfunction¶
- 功能:配合
function
使用,表示函数结束。 - 语法:
endfunction([<name>])
其中 <name>
是可选的,如果要写,必须和 function
中的 <name>
一致。
2.5 变量¶
title: cmake中变量有3种类型
1. Normal Variable(普通变量):
2. Environment Variable(环境变量):如`CC、CFLAGS、CMAKE_PREFIX_PATH`等
3. Cache Entry(缓存条目):
2.5.1 变量值获取¶
- 普通变量:
${variable}
- 环境变量:
$ENV{variable}
2.5.2 变量值设置¶
设置变量的方式有3种,可以通过以下命令设置
1. set
2. string
3. list
---
示例如下:
Strings using `set()`:
- `set(MyString "Some Text")`
- `set(MyStringWithVar "Some other Text: ${MyString}")`
- `set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"")`
Or with `string()`:
- `string(APPEND MyStringWithContent " ${MyString}")`
Lists using `set()`:
- `set(MyList "a" "b" "c")`
- `set(MyList ${MyList} "d")`
Or better with `list()`:
- `list(APPEND MyList "a" "b" "c")`
- `list(APPEND MyList "d")`
- 普通变量:
set(<variable> [<value>])
- 环境变量:
set(ENV{<variable>} [<value>])
- 示例
message(STATUS "BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}" )
set(BUILD_SHARED_LIBS on )
message(STATUS "BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}" )
message(STATUS "CC=$ENV{CC}")
set(ENV{CC} g++)
message(STATUS "CC=$ENV{CC}")
add_library(MathFunctions mysqrt.cxx)
### cmake输出结果(部分)
-- BUILD_SHARED_LIBS=
-- BUILD_SHARED_LIBS=on
-- CC=/usr/bin/cc
-- CC=g++