一、cmake简介
cmake 的诞生主要是为了解决直接使用 make+Makefile 这种方式无法实现跨平台的问题,所以 cmake 是可以实现跨平台的编译工具,这是它最大的特点。cmake还包含以下优点:
⚫开放源代码
⚫跨平台:cmake 仅仅只是根据不同平台生成对应的 Makefile,最终还 是通过 make工具来编译工程源码,但是 cmake 却是跨平台的。
⚫语法规则简单
二、cmake和Makefile
cmake就是用来产生Makefile工具,解析CMakeLists.txt自动生成Makefile
三、 cmake的使用方法
cmake ./ CMakeLists.txt在当前文件夹 cmake ../ CMakeLists.txt在上一级文件夹
cmake后面携带的路径指定了CMakeLists.txt文件的所在路径apt-get 命令可以在线安装 :
cmake ./ CMakeLists.txt在当前文件夹 cmake ../ CMakeLists.txt在上一级文件夹
使用out-of-source方式构建
将构建过程生成的文件与源文件分离开来,不让它们混杂在一起;在工程目录下创建一个build目录,在build目录下执行cmake。
1.示例一:单个源文件
CMakeLists.txt文件
project(HELLO) add_executable(hello ./main.c)
2.示例二:多个源文件
CMakeLists.txt文件
project(HELLO)
set(SRC_LIST main.c hello.c)
add_executable(hello ${SRC_LIST})
3.示例三:生成库文件
CMakeLists.txt文件
project(HELLO) add_library(libhello hello.c) add_executable(hello main.c) target_link_libraries(hello libhello)
修改生成的库文件名字:
CMakeLists.txt 文件:
project(HELLO) add_library(libhello SHARED hello.c) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello") add_executable(hello main.c) target_link_libraries(hello libhello)
不可以直接修改add_library命令的参数add_library(hello hello.c)
目标名对于整个工程来说是唯一的,不可出现相同名字的目标
我们只需要在 CMakeLists.txt文件中添加下面这条命令即可:
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
4.示例四:将源文件组织到不同的目录
将源文件按照类型、功能、模块给它们放置到不同的目录下
⚫ 顶层CMakeLists.txt
cmake_minimum_required(VERSION 3.5) project(HELLO) add_subdirectory(libhello) add_subdirectory(src)
⚫ src目录下的CMakeLists.txt
include_directories(${PROJECT_SOURCE_DIR}/libhello)
add_executable(hello main.c)
target_link_libraries(hello libhello)
⚫ libhello目录下的CMakeLists.txt
add_library(libhello hello.c) set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
和前面一样,进入到 build 目录下进行构建、编译,最终会得到可执行文件 hello(build/src/hello)和库文件 libhello.a(build/libhello/libhello.a)
5.示例五:将生成的可执行文件和库文件放置到单独的目录下
让可执行文件单独放置在 bin 目录下,而库文件单独放置在 lib 目录下
将 src 目录下的 CMakeList.txt 文件进行修改, 如下所示:
include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
add_executable(hello main.c)
target_link_libraries(hello libhello)
然后再对 libhello 目录下的 CMakeList.txt 文件进行修改,如下所示:
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
add_library(libhello hello.c)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
EXECUTABLE_OUTPUT_PATH 变量控制可执行文件的输出路径,而
LIBRARY_OUTPUT_PATH 变量控制库文件的输出路径。
- CMakeLists.txt语法规则
1.简单地语法介绍
⚫ 注释
在 CMakeLists.txt 文件中,使用“#”号进行单行注释
大多数脚本语言都是使用“#”号进行注释。
⚫ 命令(command)
多个参数使用空格分隔而不是逗号“,”,这是与函数不同的地方。
命令的语法格式如下所示:
command(参数1 参数2 参数3 ...) 不同的命令所需的参数不同
参数可以分为必要参数和可选参数(通常称为选项)很多命令都提供了这两类参数,必要参数使用<参数>表示,而可选参数使用[参数]表示
譬如 set 命令: set(
在 CMakeLists.txt 中,命令名不区分大小写,可以使用大写字母或小写字母书写命令名
譬如:
project(HELLO) #小写 PROJECT(HELLO) #大写
这俩的效果是相同的,指定的是同一个命令,并没区别;这个主要看个人喜好,个人喜欢用小写字母,主要是为了和变量区分开来,因为 cmake 的内置变量其名称都是使用大写字母组成的。
⚫ 变量(variable)
变量可以分为 cmake 内置变量以及自定义变量,譬如下例中所定义的MY_VAL 就是一个自定义变量;譬如在32.3.5小节中所使用的 LIBRARY_OUTPUT_PATH 和 EXECUTABLE_OUTPUT_PATH 变量则是cmake 的内置变量,每一个内置变量都有自己的含义
使用 set 命令可以对变量进行设置
# 设置变量 MY_VAL
set(MY_VAL "Hello World!")
通过${MY_VAL}方式来引用变量
#引用变量 MY_VAL
message(${MY_VAL})
2.常用命令
cmake提供了很多命令,每一个命令都有它自己的功能、作用,通过这个链接地 址
https://cmake.org/cmake/help/v3.5/manual/cmake-commands.7.html
可以查询到所有的命令及其相应的介绍、使用方法等等。
基本命令:
1.常用变量
变量也是 cmake 中的一个重头戏,cmake 提供了很多内置变量,每一个变量都有它自己的含义,通过这个链接地址
https://cmake.org/cmake/help/v3.5/manual/cmake-variables.7.html
可以查询到所有的内置变量及其相应的介绍。
⚫ 提供信息的变量
⚫ 改变行为的变量
⚫ 描述系统的变量
⚫ 控制编译的变量
- 双引号的作用
命令参数
命令中多个参数之间使用空格进行分隔,而 cmake会将双引号引起来的内容作为一个整体,当它当成一个参数。
引用变量
# CMakeLists.txt
set(MY_LIST Hello World China)
message(${MY_LIST})
这个例子的打印信息如下: HelloWorldChina
不加双引号时,CMake不会数组当成一个整体看待,而是会将数组中的各个元素提取出进行打印输出。
# CMakeLists.txt
set(MY_LIST Hello World China)
message("${MY_LIST}")
此时 message 打印信息如下: Hello;World;China
表示要让 CMake 把这个数组的所有元素当成一个整体,而不是分散的个体。于是,为了保持数组的含义,又提供一个整体的表达方式,CMake 就会用分号“;”把这数组的多个元素连接起来。
- 条件判断
在 cmake 中可以使用条件判断,条件判断形式如下:
else和endif 括号中的
expression 就是一个进行判断的表达式
可以通过
https://cmake.org/cmake/help/v3.5/command/if.html
这个链接地址进行查看,现在我们对上表中的表达式进行详解。
- 循环语句
(1)foreach 循环
①、foreach 基本用法
foreach 循环的基本用法如下所示:
endforeach 括号中的
# foreach 循环测试
foreach(loop_var A B C D)
message("${loop_var}")
endforeach()
打印信息为:
A
B
C
D
使用 foreach 可以编译一个列表中的所有元素,如下所示:
# foreach 循环测试
set(my_list hello world china)
foreach(loop_var ${my_list})
message("${loop_var}")
endforeach()
打印信息如下:
Hello
World
china
②、foreach循环之RANGE关键字
用法如下所示:
foreach(loop_var RANGE stop) foreach(loop_var RANGE start stop [step])
对于第一种方式,循环会从 0 到指定的的数字 stop,包含 stop,stop 不能为负数。
而对于第二种,循环从指定的数字 start开始 stop结束,步长为 step,不过 step 参数是一个可选参数,如果不指定,默认step=1;三个参数都不能为负数,而且 stop不能比start小。
③、foreach 循环之IN关键字
用法如下:
foreach(loop_var IN [LISTS [list1 [...]]] [ITEMS [item1 [...]]])
循环列表中的每一个元素,或者直接指定元素。
接下来进行测试,测试一:
# foreach 循环测试
set(my_list A B C D)
foreach(loop_var IN LISTS my_list)
message("${loop_var}")
endforeach()
打印信息如下:
A
B
C
D
测试二:
# foreach 循环测试
foreach(loop_var IN ITEMS A B C D)
message("${loop_var}")
endforeach()
打印信息同上。
二、while 循环
while 循环用法如下:
endwhile 括号中的 condition 可写可不写,如果写了,就必须和 while 中的 condition 一致。 cmake 中 while 循环的含义与 C 语言中 while 循环的含义相同,但条件 condition 为真时,执行循环体中的命令,而条件 condition 的语法形式与 if 条件判断中的语法形式相同。
输出结果如下 4 3 2 1
上例中,while 循环的条件是(loop_var GREATER 0),等价于(loop_var > 0),执行while 循环体
三、break、continue
①、break
break()命令用于跳出循环
②、continue
continue()命令用于结束本次循环,执行下一次循环
- 数学运算 math
math(EXPR
math 命令中,第一个参数是一个固定的关键字 EXPR,第二个参数是一个返回参数,将数学运算结果 存放在这个变量中;而第三个参数则是一个数学运算表达式,支持的运算符包括:+(加)、-(减)、*(乘)、 /(除)、%(求余)、|(按位或)、&(按位与)、^(按位异或)、~(按位取反)、<<(左移)、>>(右 移)以及这些运算符的组合运算,它们的含义与 C 语言中相同。



