条件判断
语法格式
if(<condition>)
...
elseif(<condition>)
...
elseif(<condition>)
...
else()
...
endif()
常量判断if(<constant>)
-
ON, YES, TRUE, Y,非0(包括浮点数和负数)
为真 -
0,NO, FALSE, N, IGNORE, NOTFOUND ,空字符串, xxx-NOTFOUND
为假 - 变量的值为第一种情况 --- 真, 第二种情况 -- 假, 未定义的为假, 环境变量总是假(它不认识),宏不是变量,除第一种情况外,其它都为假
- 字符串 --- 值为
真的常量
为真,否则假
if(ON)
message("ON 是真")
endif()
if(NOT "HELLO")
message("HELLO 字符串 -- 假")
endif()
if("y")
message("字符串 y 是真")
endif()
set(VAR TRUE)
if(VAR)
message("对于变量,不需要加\${}")
endif()
小结
- 除了
ON, YES, TRUE, Y,非0(包括浮点数和负数)
- 变 量值为
'真常量'
-
字符串为真常量
除以上情况外,其它的都是false
逻辑操作符
if(<NOT condition>)
if(<condition1 AND condition2>)
if(<condition1 OR condition2>)
if(<(condition1 OR condition2) AND condition3>)
- 可以用()提高优先级
一元,二元比比较和正则匹配
一元
- EXISTS -- 文件是否存在??
- COMMAND -- 是否是一个
cmake
指令 - DEFINED -- 变量是否定义了
set(VAR "")
if(DEFINED VAR)
message("var is define ")
endif()
if(COMMAND project)
message("project is cmake command")
endif()
二元
- 数字符判断
EQUAL, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL
- 字符串判断
STREQUAL, STRLESS, STRLESS_EQUAL, STRGREATER, STRGREATER_EQUAL
- 版本号
VERSION_EQUAL, VERSION_LESS, VERSION_LESS_EQUAL, VERSION_GREATER, VERSION_GREATER_EQUAL
if(1 EQUAL 1)
message("相等")
endif()
if("100" EQUAL "100") # 也可以判断字符串
message("100 相等")
endif()
正则匹配 MATCHES
if(<variable|string> MATCHES regx)
if("123abcd" MATCHES ".*\\d+.*$") # 包含一个以上的数字
message("matches")
endif()
变量和缓存
- 持久化存储,第一次生成之后,第二次的值不会改变
- 普通变量只能在当前文件或子目录有效,而缓存变量是全局的
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
type
- BOOL 开关
- FILEPATH 选择文件
- PATH 选择目录
- STRING 需要手动输入
- INTERNAL 内置变量,不会在ccmake 或 guimake中显示
- type
ccmake
时根据不同类型,有不同的操作类型 - docstring 文档
- FORCE 如果没有,第一次设置后,第二次设置不会生效
需要安装ccmake
sudo apt install cmake-curses-gui
cmake -S . -B build # 需要先生成
ccmake build/ # 修改cache变量
cmake --build build/ # 编译
简化语法 -- BOOL类型
option(VARIABLE "docstring" <ON|OFF>)
复盖策略
当普通变量与缓存变量重名时的复盖策略
cmake_policy(SET CMPC126 NEW) # 3.21之后才支持,NEW 不删除普通变量, OLD删除普通变量
内置缓存变量
不配置,guimake就有的变量。
-D命令行传递缓存变量
cmake -S . -B build -D VARIABLE_NAME=VALUE
cmake -S . -B build -D BUILD_SHARED_LIBS=ON
CMake
属性与变量
属性和变量有什么区别
成员变量,附在某个目标上,全局属性。
属性语法
set_property
set_property(
<
GLOBAL |
DIRCTORY [<dir>] |
TARGET [<target> ...] |
SOURCE [<src> ...]
[DIRECTORY <dirs>...]
[TARGET_DIRECTORY <targets>...] |
INSTALL [<file> ...] |
TEST [<test> ...] |
CACHE [<entry> ...]
>
[APPEND] [APPEND_STRING]
PROPERTY <name> [<value> ...]
)
get_property
get_property(
<variable>
<
GLOBAL |
DIRCTORY [<dir>] |
TARGET [<target> ...] |
SOURCE [<src> ...]
[DIRECTORY <dirs>...]
[TARGET_DIRECTORY <targets>...] |
INSTALL [<file> ...] |
TEST [<test> ...] |
CACHE [<entry> ...]
>
PROPERTY <name>
[SET | DEFINE | BRIEF_DOCS | FULL_DOCS] # 属性是否定义,设置? 说明文档
)
define_property(
<GLOBAL | DIRECTORY | TARGET | SOURCE |TEST VARIBALE ...>
PROPERTY <name> [INHERITED]
.....
)
使用示例
set_property(GLOBAL PROPERTY P1 "p1")
get_property(V GLOBAL PROPERTY P1 SET)
get_property(V2 GLOBAL PROPERTY P1 DEFINED)
message("${V}") # 1 判断属性是否被设置
message("${V2}") # 0
define_property(GLOBAL PROPERTY P3 BRIEF_DOCS "brief docs")
get_property(V2 GLOBAL PROPERTY P3 DEFINED )
get_property(V3 GLOBAL PROPERTY P3 BRIEF_DOCS )
message("${V2}") # 1 判断P3是否有define
message("${V3}")
set_property(SOURCE main.cpp PROPERTY S1 "s1 value")
get_property(main_s1 SOURCE main.cpp PROPERTY S1)
message("${main_s1}")
# 文件属性 给 C++ 传值
set_property(SOURCE main.cpp PROPERTY COMPILE_DEFINITIONS "P=1234") # -D P=1234
add_executable(main main.cpp)
打印属性
include(CMakePrintHelpers)
cmake_print_properties(GLOBAL PROPERTIES P1 P2 ...)
环境变量
不常用,只影响cmake进行,只用于生成。
set(ENV {<variable>} {<value>})
$ENV{<variable>}
message("$ENV{PATH}")
math
数学计算
math(EXPR <variable> "expression" [OUTPUT_FORMAT <format>])
math(EXPR var "5 * (3 + 4) / 6" OUTPUT_FORMAT HEXADECIMAL) # 不支持浮点数
message("${var}")
string
字符串
- 查找和替换
- 操作 -- 追加,拼接,大小写切换,求长度,求子串,去除空白
- 比较
- 哈希
- 生成
- JSON
查找和相关处理
set(STR1 "begin test cmake string end")
string(LENGTH ${STR1} len) # 27
string(FIND ${STR1} "begin" index) # 0
string(FIND ${STR1} "end" index1) # 24
string(LENGTH "begin" len)
message("${len}")
string(LENGTH "begin" len)
math(EXPR start "${index} + ${len}")
set(end ${index1})
message("${end}")
math(EXPR len1 "${end} - ${len}")
string(SUBSTRING ${STR1} ${start} ${len1} var)
message("[${var}]")
string(STRIP ${var} v1)
message("[${v1}]")
追加/正则
string(APPEND substr "a" "b")
string(REPLACE "a" "b" substr substr)
string(REGEX MATH "[a-z]+" out ${substr})
json
string(
JSON <out> [ERROR_VARIBLE var]
{GET | TYPE | LENGTH | REMOVE}
<json> <member | index [<member | index> ...]>
)
set(json
[=[
{
"webs": {
"web": [
{
"name": "cmake",
"url": "cmake.url"
}
]
}
}
]=])
message("${json}")
string(JSON out ERROR_VARIABLE err GET ${json} webs web 0 name) # cmake
message(${out})
# 增加和修改
string(JSON out ERROR_VARIABLE err SET ${json} webs web 1 [=[
{
"name": "ffmpeg",
"url": "ffmpeg.org.com"
}
]=])
string(JSON out ERROR_VARIABLE err SET ${out} webs web 0 [=[
{
"name": "unknow",
"url": "unknow.org.com"
}
]=])
message(${out})
string(JSON out ERROR_VARIABLE err REMOVE ${out} webs web 0)
message(${out})
cmake list
操作
list就是用也是一个字符串,每项之前用;
分隔a;b;c;d
set(srcs a.c b.c c.c) # a.c;b.c;c.c
set(x a "b;c") # a;b;c
set(var a b c d e f "g;h")
message("${var}")
list(APPEND var xx yy)
list(LENGTH var length)
message("${length}")
list(GET var 0 e1)
list(GET var -1 e2)
message("${e1}")
message("${e2}")
list(JOIN var "|" lst)
message("${lst}")
# 子串
list(SUBLIST var 0 3 out)
message("${out}")
list(FIND var "b" index)
message("${index}")
list(INSERT var 1 "insert")
message("${var}")
list(REMOVE_AT var 2)
list(INSERT var 2 E)
message("${var}")
队列的操作
list(POP_BACK var e)
list(POP_FRONT var e1)
# 去重
list(REMOVE_DUPLICATES var)
message("${var}")
list(SORT var) # 字符串排序
set(lst 3 2 4 5 1)
list(SORT lst COMPARE NATURAL)
message("${lst}")
循环
foreach (var items)
<commands(var)>
endforeach()
foreach(e ${lst})
message(${e})
endforeach()
foreach(e a1 a2 a3 a4 a5)
message(${e})
endforeach()
foreach(var RANGE stop)
commands
endforeach()
foreach(var RANGE start stop [step])
commands
endforeach()
foreach(e RANGE 9)
message(${e})
endforeach()
foreach(e RANGE -1 -10 -2)
message(${e})
endforeach()
IN? -- 针对数组操作
foreach(e IN LISTS var lst) # 先合并再遍历
message(${e})
endforeach()
# 打包成对
foreach(e e1 IN ZIP_LISTS var lst)
message("${e} ${e1}")
endforeach()
break和continue
foreach(e RANGE -1 -10 -2)
message(${e})
if(e EQUAL 5)
[break() | continue()]
endif()
endforeach()
while
while(<condition>)
command
endwhile()
set(var 1)
while(var)
math(EXPR var "${var} + 1")
if(var GREATER 100)
break()
endif()
endwhile()
宏和函数
宏
macro(foo)
<commands>
endmacro()
- 大小写不敏感
- 官方推荐用小写
- 函数方式的调用
foo()
参数
macro(foo arg1 arg2)
- 如果不设定参数,则用可以传任意个数的参数
- 如果设定了能数,则指定的参数必须要传,可以传指定参数以外的..., 类似于python的必须参数
- ARGC -- 参数个灵敏
- ARGN -- 参数数组, 不包含必须参数
- ARGV0 ARGV1 ARGV2 ...
macro(foo a1 a2)
message("argc = ${ARGC} ARGV0 = ${ARGV0} ARGV1 = ${ARGV1} a1 = ${a1} a2 = ${a2}")
endmacro()
foo(1 2 3 4) #
- 宏参数不是变量,取值须有
${ARGN}
foreach(v IN LISTS ARGN)
if(ARG1) 不能用 - 宏的调用变是替换,与C/C++类似
属性式参数
foo(TARGETS bar xxx yyy DESTINATION bin)
cmake_parse_arguments(<...>)
- perfix
- options
- one_value_keywords
- multi_value_keywords
- _UNPARSED_ARGUMENTS
macro(mypass)
cmake_parse_arguments(
"MY" # perfix
"LOG;FILE" # option
"LIB;BIN" # one_value_keywords
"APPS;NAMES" # multi_value_keywords
${ARGN}
)
message("${MY_LOG} ${MY_FILE}")
message("${MY_LIB} ${MY_BIN}")
message("${MY_APPS} ${MY_NAMES}")
message("MY_UNPARSED_ARGUMENTS = ${MY_UNPARSED_ARGUMENTS}")
endmacro(mypass)
mypass(LOG "abb" LIB "lib" BIN "bin" APPS 1 2 3 4 NAMES N A B)
函数
- 参数是变量
- 内置设置的变量只在函数内有作用域 --
set(ret 1 PARENT_SCOPE)
给上层传值(父目录) - 可以return -- 结束作用域,不能返回值