1、CMake简介
cmake是makefile的上层工具,它们的目的正是为了产生可移植的makefile,并简化自己动手写makefile时的巨大工作量。在linux平台下使用CMake生成Makefile并编译的流程如下:
- 编写CMake配置文件CMakeLists.txt 。
- 执行命令cmake PATH生成Makefile。其中PATH是CMakeLists.txt所在的目录。因为CMake往往会生成很多文件,让工程层级看起来不清晰了,所以有一个比较好的方法是再建立一个build文件夹。
- 使用make命令进行编译。
CMake执行命令如下:
mkdir build
cd build
cmake ..
make -j
CMake执行命令解释如下:
- 编写cmake配置文件CMakeLists.txt。通常CMakeLists.txt放在项目顶层目录,根据需要也可在子目录放置。
- 在CMakeLists.txt文件所在目录下创建一个build文件夹,然后进入目录。不建目录理论上是可行的,但是生成的中间文件不易清理,另外build目录名词也是可以自定义的。
- 执行cmake ..生成makefile。
- 执行make和make install进行编译和安装。
2、CMake语法
2.1、CMake注释
(1)单行注释:#注释内容
(2)多行注释:可以使用括号来实现多行注释:
#[[ 多行注释
多行注释
多行注释 ]]
2.2、CMake变量
(1)CMake中所有的变量都是string类型。
(2)set() / unset():声明 / 移除一个变量。
(3)声明变量:set(变量名 变量值)。
set(var 123)
(4)引用变量:${变量名}
${var}
(6)打印变量:message("变量名 = ${变量名}")
message("var = ${var}")
2.3、CMake常用变量
CMake预设了一些常用变量,这些变量通常会在编写CMakeLists.txt文件时使用到:
CMAKE_MAJOR_VERSION:cmake主版本号。
CMAKE_MINOR_VERSION:cmake次版本号。
CMAKE_C_FLAGS:设置C编译选项。
CMAKE_CXX_FLAGS:设置C++编译选项。
PROJECT_SOURCE_DIR:工程的根目录。
PROJECT_BINARY_DIR:运行cmake命令的目录。
CMAKE_CURRENT_SOURCE_DIR:当前CMakeLists.txt 所在路径。
CMAKE_CURRENT_BINARY_DIR:目标文件编译目录。
EXECUTABLE_OUTPUT_PATH:重新定义目标二进制可执行文件的存放位置。
LIBRARY_OUTPUT_PATH:重新定义目标链接库文件的存放位置。
UNIX:如果为真,表示为UNIX-like的系统,包括AppleOSX和CygWin。
WIN32:如果为真,表示为Windows系统,包括 CygWin。
APPLE:如果为真,表示为Apple系统。
CMAKE_SIZEOF_VOID_P:表示void*的大小(例如为4或者8),可以使用其来判断当前构建为32位还是64位
CMAKE_CURRENT_LIST_DIR:表示正在处理的CMakeLists.txt文件所在目录的绝对路径
CMAKE_ARCHIVE_OUTPUT_DIRECTORY:用于设置ARCHIVE目标的输出路径。
CMAKE_LIBRARY_OUTPUT_DIRECTORY:用于设置LIBRARY目标的输出路径。
CMAKE_RUNTIME_OUTPUT_DIRECTORY:用于设置RUNTIME目标的输出路径。
2.4、CMake列表(LISTS)
(1)列表也是字符串,可以把列表看做是一个特殊的变量,这个变量有多个值。
(2)语法格式:set(列表名 值1 值2 ... 值n) 或 set(列表名 “值1;值2;...值n”)
(3)声明列表:set(列表名 值1 值2 ... 值n) 或 set(列表名 “值1;值2;...值n”)
set(list_var 1 2 3 4 5) 或 set(list_var "1;2;3;4;5")
(4)引用列表:${列表名}
(5)打印列表:message("列表名 = ${列表名}")
message("list_var = ${list_var}")
2.5、流程控制
(1)条件命令if():
语法格式:
if (表达式)
COMMAND(ARGS...)
elseif(表达式)
COMMAND(ARGS...)
else(表达式)
COMMAND(ARGS...)
endif(表达式)
示例:
set(if_tap OFF)
set(elseif_tap ON)
if(${if_tap})
message("if")
elseif(${elseif_tap})
message("elseif")
else(${if_tap})
message("else")
endif(${if_tap})
elseif和else部分是可选的,也可以使用多个elseif部分。缩进和空格对语句的解析没有影响。
(2)循环命令while():
语法格式:
while(表达式)
COMMAND(ARGS...)
endwhile(表达式)
示例:
set(a "")
while(NOT a STREQUAL "xxx")
set(a "${a}x")
message("a = ${a}")
endwhile()
break()可以跳出整个循环;continue() 可以跳出当前循环。
(3)循环遍历 foreach():
语法格式:
foreach(循环变量 参数1 参数2... 参数N)
COMMAND(ARGS...)
endforeach(循环变量)
遍历RANGE:
#循环范围从start到stop,循环增量为step
foreach(循环变量 RANGE start stop step)
COMMAND(ARGS...)
endforeach(循环变量)
遍历LISTS:
foreach(循环遍历 IN LISTS 列表)
COMMAND(ARGS...)
endforeach(循环变量)
示例:
foreach(item 1 2 3)
message("item = ${item}")
endforeach(item)
#RANGE:RANGE 4 表示从0到4
foreach(item RANGE 4)
message("item = ${item}")
endforeach(item)
#RANGE:打印 1 3 5
foreach(item RANGE 1 5 2)
message("item = ${item}")
endforeach(item)
#LISTS:
set(list_var 1 2 3)
foreach(item IN LISTS list_var)
message("item = ${item}")
endforeach(item)