0
点赞
收藏
分享

微信扫一扫

CMake系统学习3 -- CMake基础语法

条件判断

语法格式

if(<condition>)
...
elseif(<condition>)
...
elseif(<condition>)
...
else()
...
endif()

常量判断​​if(<constant>)​

  1. ​ON, YES, TRUE, Y,非0(包括浮点数和负数)​​ 为真
  2. ​0,NO, FALSE, N, IGNORE, NOTFOUND ,空字符串, xxx-NOTFOUND ​​ 为假
  3. 变量的值为第一种情况 --- 真, 第二种情况 -- 假, 未定义的为假, 环境变量总是假(它不认识),宏不是变量,除第一种情况外,其它都为假
  4. 字符串 --- 值为​​真的常量​​为真,否则假

if(ON)
message("ON 是真")
endif()

if(NOT "HELLO")
message("HELLO 字符串 -- 假")
endif()

if("y")
message("字符串 y 是真")
endif()
set(VAR TRUE)
if(VAR)
message("对于变量,不需要加\${}")
endif()

小结

  1. 除了​​ON, YES, TRUE, Y,非0(包括浮点数和负数)​
  2. 变 量值为​​'真常量'​
  3. ​字符串为真常量​

除以上情况外,其它的都是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 -- 结束作用域,不能返回值
举报

相关推荐

0 条评论