1、CMake简介
CMake是一个跨平台的编译工具,可以用简单的语句来描述所有平台的编译过程。
Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。
2、CMake中的变量
变量 名 | 含义 |
PROJECT_SOURCE _DIR (等价于CMAKE_SOURCE_DIR ) | 工程的根目录,及顶层CMakelists.txt文件的所在目录 |
PROJECT_BINARY_DIR (等价于CMAKE_BINARY_DIR ) | 运行 cmake 命令的目录,通常是 build/ |
CMAKE_CURRENT_SOURCE_DIR | 对于CMake嵌套调用时,表示当前正在执行的CMakeList.txt的路径 |
CMAKE_CURRENT_BINARY_DIR | 目标编译目录 |
CMAKE_CURRENT_LIST_DIR | CMakeLists.txt 的完整路径 |
CMAKE_CURRENT_LIST_LINE | 当前所在的行 |
EXECUTABLE_OUTPUT_PATH | 重新定义目标二进制可执行文件的存放位置 |
LIBRARY_OUTPUT_PATH | 重新定义目标链接库文件的存放位置 |
CMAKE_MODULE_PATH | 定义自己的 cmake 模块所在的路径,SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块 |
PROJECT_NAME | 返回通过 project 命令定义的项目名称 |
3、CMake中的函数
1)设置最小版本
cmake_minimum_required(VERSION 3.4.1)
当 CMakeLists.txt 文件中使用了一些高版本 cmake 特有的一些命令的时候,就需要加上这样一行,提醒用户升级到该版本之后再执行 cmake。
2)设置项目名称
project(main) #通过${PROJECT_NAME}可访问此函数设置的项目名字,即"main"。
3)操作变量
set(SRC_LIST main.cpp) #创建变量SRC_LIST
set(SRC_LIST ${SRC_LIST} test.cpp) #向变量SRC_LIST追加内容
list(APPEND SRC_LIST uart.cpp) #向变量SRC_LIST追加内容
list(REMOVE_ITEM SRC_LIST test.cpp) #删除变量SRC_LIST中的指定值
4)变量打印
message(${PROJECT_SOURCE_DIR})
message("print string")
message(WARNING "This is a warnning message")
message(FATAL_ERROR "fatal error has occurred") #致命等级错误将导致编译失败
5)设置编译类型
add_executable(demo main.cpp) # 生成可执行文件main
add_library(common uart.cpp) # 生成静态库libuart.a
add_library(common STATIC uart.cpp) # 生成静态库libuart.a
add_library(common SHARED uart.cpp) # 生成动态库或共享库libuart.so
add_subdirectory(uart/) # 添加子目录uart,并执行uart目录下的CMakeLists.txt
6)设置资源路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc) #设置头文件的搜索目录
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib) #设置库文件的搜索目录
#上述过程等价于
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/inc")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/lib")
7)添加库文件
#下述两种方式都是在link_directories设置目录下进行搜索的
link_libraries(-pthread uart) #链接线程库和libuart.so
target_link_libraries(${PROJECT_NAME} pthread uart) #链接线程库和libuart.so
上述链接的库,可以显示地指定为静态的或动态的,若未指定,则优先使用动态库。指定方法如下:
link_libraries(libuart.so) #链接libuart.so
target_link_libraries(${PROJECT_NAME} libuart.so) #链接libuart.so
注意:这两个函数的功能相同,但用法略有不同。其中link_directories通常用在add_execable之前,而target_link_directories则在其后。
8)文件搜索
aux_source_directory(. SRC_LIST) #搜索当前目录下的所有源文件,不递归搜索子目录
#也可以自定义搜索规则
file(GLOB SRC_LIST "*.cpp" "uart/*.cpp") #搜索当前目录下和uart目录下所有的cpp文件
file(GLOB_RECURSE SRC_LIST "*.cpp") #从当前目录进行递归搜索,搜索所有的cpp文件
9)添加依赖
#当main的生成需要依赖于uart库和sound库时,添加此语句,可先编译依赖的库
add_dependencies(main libuart.so libsound.so)
10)宏的传递
#向程序中传递宏X86和LINUX,则程序中可以使用"#ifdef LINUX"
add_definitions(-DX86 -DLINUX)
#等价于
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -DLINUX") #C语言
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLINUX") #C++
11)编译控制
#CMake代码
option(TEST_DEBUG "option for debug" OFF) #默认TEST_DEBUG为OFF态
if (TEST_DEBUG)
add_definitions(-DTEST_DEBUG) #向源代码中传递宏TEST_DEBUG
endif()
#CMake命令
cmake -DTEST_DEBUG=ON . #向当前文件夹的CMakeLists传递CMake宏TEST_DEBUG,其值为ON
12)引入外部功能包(find_package)
参考:Cmake之深入理解find_package()的用法 - 知乎 (zhihu.com)
13)在CMake执行子进程(execute_process)
参考:CMake命令之execute_process - 程序园 (aiuxian.com)
4、CMake中的语法
1)if
常见用法:
if(TEST_DEBUG)
#操作
else()
#操作
endif()
逻辑判断:
if (expr) #判断是否为空,其中空的范围包括(0,N,NO,OFF,FALSE,NOTFOUND)
if (not expr) #非
if (var1 AND var2) #与
if (var1 OR var2) #或
if (variable LESS number) #小于
if (variable GREATER number) #大于
if (variable EQUAL number) #等于
#判断变量是否被定义过,而不关心变量的值
if (DEFINED var)
字符串比较:
if (variable STRLESS string) #小于
if (variable STRGREATER string) #大于
if (variable STREQUAL string) #等于
if (variable MATCHES regex) #正则匹配
系统操作:
if (COMMAND cmd) #判断cmd是否为可执行命令
if (EXISTS file) #判断文件是否存在
if (EXISTS dir) #判断目录是否存在
if (IS_DIRECTORY dir) #判断变量dir是否为目录
#判断file1是否比file2新。注意:file1、file2中有一个不存在时也为真,且文件名需使用全路径
if (file1 IS_NEWER_THAN file2)
2)foreach
foreach(i RANGE 1 7 2) #其中1表示起始值,7表示终止值,2为步长。即i∈[1,7]
message(${i}) #依次输出的结果为1357
endforeach(i)
3)while
while(condition)
#操作
endwhile()
4、范例
cmake_minimum_required(VERSION 2.8)
project(awake_aiui) #设置项目名称
set(CMAKE_CXX_STANDARD 11) #使用c11标准
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DAIUI_LINUX") #向源代码传递宏AIUI_LINUX
include_directories(${CMAKE_CURRENT_LIST_DIR}/../../include) #设置头文件搜索目录
link_directories(${CMAKE_CURRENT_LIST_DIR}/../../libs/x64) #设置库文件搜索目录
link_libraries(aiui -pthread msc rt dl asound) #添加动态库
add_execute(${PROJECT_NAME} #创建可执行程序awake_aiui
src/FileUtil.cpp
src/AIUITest.cpp
src/demo.cpp
src/jsoncpp/json_reader.cpp
src/jsoncpp/json_value.cpp
src/jsoncpp/json_writer.cpp
src/linuxrec.c
)
5、参考资料
1)CMakeLists.txt 语法介绍与实例演练_阿飞的博客-CSDN博客_cmakelist
2)ROS CMakelist.txt教程_LeonShen的博客-CSDN博客_cmakelists.txt 教程
3)CMake学习笔记二:cmake 常用变量和常用环境变量 - fengMisaka - 博客园 (cnblogs.com)
4)Cmake之深入理解find_package()的用法 - 知乎 (zhihu.com)