《Cmake构建实战》3 Cmake基础语法学习
本帖最后由 maskmoo 于 2024-10-20 21:45 编辑<p>第3章主要描述Cmake的基本使用语法,结合书中的实例整理如下</p>
<p><strong>CMake程序</strong></p>
<p>cmake的文件类型包括CMakeList.txt文件和扩展名为.cmake的文件。其中CMakeList.txt是用于组织构建项目源文件的目录结构,.cmake文件可以作为脚本和模块两种类型。</p>
<p>目录(CMakeList.txt) 脚本(<script>.cmake) 模块 (<module>.cmake)<br />
<strong>注释</strong></p>
<p>主要分为单行注释和多行注释,其中多行注释本质上是单行注释+括号参数的组成形式</p>
<pre>
<code class="language-bash">#单行注释
#[=[多行注释 ]=]
</code></pre>
<p><br />
<strong>命令调用</strong></p>
<p>message if for等</p>
<p><br />
<strong>命令参数</strong></p>
<p>引号参数</p>
<pre>
<code>#包含换行
message("CMake
你好!")
#不包含换行
message("\
CMake\
您好!\
")</code></pre>
<p> </p>
<p> </p>
<p>非引号参数 </p>
<pre>
<code>message("x;y;z") # 引号参数
message(x y z) # 多个非引号参数
message(x;y;z) # 非引号参数</code></pre>
<p> </p>
<p>变量引用</p>
<pre>
<code>set(var_a 您好)
set(var_b a)
message(${var_${var_b}})</code></pre>
<p> </p>
<p>转义字符 </p>
<pre>
<code>cmake_minimum_required(VERSION 3.20)
set("a?b" "变量a?b")
# \? 转义为 ?
message(${a\?b})
message(今天是几号\?)
# \n 转义为换行符,\t 转义为制表符,\! 转义为 !
message(回答:\n\t今天是1号\!)
set("a;b" "变量a;b")
# 非引号参数中 \; 转义为 ;,且不分隔变量
message(x;y\;z)
# 引号参数中 \; 不转义
message("x;y\;z")
# 变量引用中 \; 转义为 ;
message("${a\;b}")
</code></pre>
<p> </p>
<p>括号参数</p>
<pre>
<code>message([==[
abc
def
]==])
message([===[abc
def
]===])
message([===[
随便写终止方括号并不会导致文本结束,
因此右边这两个括号]]也会包括在原始文本中。
下一行中最后的括号也是原始文本的一部分,
因为等号的数量与起始括号不匹配。]==]
]===])</code></pre>
<p> </p>
<p> </p>
<p><strong>变量</strong></p>
<p>预定义变量</p>
<pre>
<code>message("CMake命令行:${CMAKE_COMMAND}")
message("OS:${CMAKE_HOST_SYSTEM_NAME}")</code></pre>
<p> </p>
<p>定义普通变量</p>
<p>需要注意的是变量的作用域</p>
<pre>
<code>function(f)
set(a "我是修改后的a")
set(b "我是b")
set(c "我是c" PARENT_SCOPE)
endfunction()
set(a "我是a")
f()
message("a: ${a}")
message("b: ${b}")
message("c: ${c}")</code></pre>
<p> <br />
缓存变量</p>
<pre>
<code>cmake_minimum_required(VERSION 3.20)
project(Notepad)
set(path_to_notepad "" CACHE FILEPATH "Path to notepad.exe")
# 下面的命令将会用记事本打开同一目录中的in.txt
execute_process(COMMAND "cmd" "/c"
${path_to_notepad} ${CMAKE_CURRENT_LIST_DIR}/in.txt)</code></pre>
<p> </p>
<p>环境变量</p>
<pre>
<code>message("main \$ENV{PATH}: $ENV{PATH}")</code></pre>
<p><strong>列表</strong></p>
<p>定义列表变量</p>
<pre>
<code class="language-bash">include(print_list.cmake)
set(a "a;b;c")
set(b a;b;c)
set(c a b c)
print_list(a) # 输出:a | b | c
print_list(b) # 输出:a | b | c
print_list(c) # 输出:a | b | c</code></pre>
<p> </p>
<p><br />
<strong>控制结构</strong></p>
<p>if while foreach break continue</p>
<p> </p>
<p><br />
<strong>条件语法 </strong></p>
<p>常量条件</p>
<p> </p>
<p>变量条件</p>
<pre>
<code>cmake_minimum_required(VERSION 3.20)
set(on "OFF")
if(on)
message("ON")
else()
message("OFF")
endif()
if(${on})
message("ON")
else()
message("OFF")
endif()</code></pre>
<p> </p>
<p>字符串条件 </p>
<pre>
<code>if(ABC)
else()
message("ABC不是一个已定义的变量,因此条件为假")
endif()
set(a "XYZ")
set(b "0")
set(c "a-NOTFOUND")
if(a)
message("a是一个变量,其值非假值常量,因此条件为真")
endif()
if(b)
else()
message("b是一个变量,其值为假值常量,因此条件为假")
endif()
if(c)
else()
message("c是一个变量,其值为假值常量,因此条件为假")
endif()</code></pre>
<p> </p>
<p>逻辑运算</p>
<pre>
<code>cmake_minimum_required(VERSION 3.20)
if(NOT OFF)
message("NOT OFF为真")
endif()
if(ON AND YES)
message("ON AND YES为真")
endif()
if(TRUE AND NOTFOUND)
else()
message("TRUE AND NOTFOUND为假")
endif()
if(A-NOTFOUND OR YES)
message("A-NOTFOUND OR YES为真")
endif()</code></pre>
<p></p>
<p>单参数条件</p>
<pre>
<code>set(a 1)
if(DEFINED a)
message("DEFINED a为真")
endif()
if(CACHE{b})
else()
message("CACHE{b}为假")
endif()
if(COMMAND set)
message("COMMAND set为真")
endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/逻辑运算.cmake")
message("EXISTS \"${CMAKE_CURRENT_LIST_DIR}/逻辑运算.cmake\"为真")
endif()</code></pre>
<p> </p>
<p>双参数条件</p>
<pre>
<code>cmake_minimum_required(VERSION 3.20)
set(a 10)
set(b "abc")
set(list 1;10;100)
if(11 GREATER a)
message("11 GREATER a为真")
endif()
if(1 LESS 2)
message("1 LESS 2为真")
endif()
if(b STRLESS "b")
message("b LESS \"b\"为真")
endif()
if(1.2.3 VERSION_LESS 1.10.1)
message("1.2.3 LESS 1.10.1为真")
endif()
if(abc MATCHES a..)
message("abc MATCHES a..为真")
endif()
if(ab MATCHES a..)
else()
message("ab MATCHES a..为假")
endif()
if(a IN_LIST list)
message("a IN_LIST list为真")
endif()</code></pre>
<p> </p>
<p>括号和条件优先级</p>
<pre>
<code>cmake_minimum_required(VERSION 3.20)
if(NOT TRUE AND FALSE OR TRUE)
message("NOT FALSE AND TRUE OR FALSE为真")
endif()
if(NOT (TRUE AND (FALSE OR TRUE)))
else()
message("NOT FALSE AND TRUE OR FALSE为假")
endif()</code></pre>
<p> </p>
<p>变量展开</p>
<pre>
<code>cmake_minimum_required(VERSION 3.20)
set(A FALSE)
set(B "A")
if(B)
message("B为真")
endif()
if(${B})
else()
message("\${B}为假")
endif()
while(NOT ${B})
message("NOT \${B}为真")
break()
endwhile()</code></pre>
<p> <br />
<strong>命令定义</strong></p>
<p>宏定义</p>
<pre>
<code>macro(my_macro a b)
set(result "参数a: ${a}, 参数b: ${b}")
endmacro()
my_macro(x y)
message("${result}") # 输出:参数a: x, 参数b: y
MY_macro(A;B)
message("${result}") # 输出:参数a: A, 参数b: B
MY_MACRO(你 好)
message("${result}") # 输出:参数a: 你, 参数b: 好</code></pre>
<p> </p>
<p>函数定义</p>
<pre>
<code>function(my_func a b)
set(result "参数a: ${a}, 参数b: ${b}" PARENT_SCOPE)
endfunction()
my_func(x y)
message("${result}") # 输出:参数a: x, 参数b: y
MY_func(A;B)
message("${result}") # 输出:参数a: A, 参数b: B
MY_FUNC(你 好)
message("${result}") # 输出:参数a: 你, 参数b: 好</code></pre>
<p> </p>
<p> </p>
<p>参数访问 </p>
<pre>
<code>macro(my_macro p)
message("ARGC: ${ARGC}")
message("ARGV: ${ARGV}")
message("ARGN: ${ARGN}")
message("ARGV0: ${ARGV0}, ARGV1: ${ARGV1}")
endmacro()
function(my_func p)
message("ARGC: ${ARGC}")
message("ARGV: ${ARGV}")
message("ARGN: ${ARGN}")
message("ARGV0: ${ARGV0}, ARGV1: ${ARGV1}")
endfunction()
my_macro(x y z)
my_func(x y z)</code></pre>
<p> </p>
<p>参数的设计与解析</p>
<pre>
<code>function(my_copy_func)
message("ARGN: ${ARGN}")
set(options OVERWRITE MOVE)
set(oneValueArgs DESTINATION)
set(multiValueArgs PATHS)
cmake_parse_arguments(
my
"${options}" "${oneValueArgs}" "${multiValueArgs}"
${ARGN}
)
message("OVERWRITE:\t${my_OVERWRITE}")
message("MOVE:\t\t${my_MOVE}")
message("DESTINATION:\t${my_DESTINATION}")
message("PATHS: \t\t${my_PATHS}")
message("---")
endfunction()
my_copy_func(DESTINATION ".." PATHS "1.txt" "2.txt" OVERWRITE)
my_copy_func(MOVE DESTINATION "../.." PATHS "3.txt" "4.txt")
my_copy_func(DESTINATION "../folder;name" PATHS 1.txt;2.txt)</code></pre>
<p> </p>
<p>宏和函数参数的区别</p>
<pre>
<code>macro(my_macro p)
message("-- my_macro --")
if(p)
message("p为真")
endif()
set(i 1)
message("ARGV i: ${ARGV${i}}")
endmacro()
function(my_func p)
message("-- my_func --")
if(p)
message("p为真")
endif()
set(i 1)
message("ARGV i: ${ARGV${i}}")
endfunction(my_func)
my_macro(ON x)
my_func(ON x)</code></pre>
<p> </p>
<p>感谢楼主分享的cmake基本语法知识,内容详实,通俗易懂,受益匪浅</p>
页:
[1]