一:最小组成
# cmake 最小版本需求
cmake_minimum_required(VERSION 2.8)
# project 名字
project(MyEsp32AllCode)
# 可执行文件生成
add_executable(${PROJECT_NAME} "main.c")
二:.h .c .cpp 文件添加
1:include_directories
提供了搜索头文件的根目录
例如:/home/xx/include/opencv/cv.h
可以在cmakelists.txt 中写上
include_directories(/home/xx/include)来让库文件搜索以/home/xx/include为基础
即可在main.c 函数上 添加 #include “opencv/cv.h" 来应用。
2:find_package()
例子1:(版本错误)
find_package(Boost 1.68.0 REQUIRED system coroutine thread)
输出
CMake Error at /usr/share/cmake-3.10/Modules/FindBoost.cmake:1947 (message):
Unable to find the requested Boost libraries.
Boost version: 1.65.1
Boost include path: /usr/include
Detected version of Boost is too old. Requested version was 1.68 (or
newer).
Call Stack (most recent call first):
CMakeLists.txt:29 (find_package)
Configuring incomplete, errors occurred!
本地安装boost 版本 为1.65.1 修改为
find_package(Boost 1.65 REQUIRED system coroutine thread)
- –>
Boost version: 1.65.1
Found the following Boost libraries:
system
coroutine
thread
context
chrono
date_time
atomic
例子2:(找不到相应库)
find_package(eigen3 REQUIRED)
输出
CMake Error at CMakeLists.txt:44 (find_package):
By not providing "Findeigen3.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "eigen3", but
CMake did not find one.
Could not find a package configuration file provided by "eigen3" with any
of the following names:
eigen3Config.cmake
eigen3-config.cmake
Add the installation prefix of "eigen3" to CMAKE_PREFIX_PATH or set
"eigen3_DIR" to a directory containing one of the above files. If "eigen3"
provides a separate development package or SDK, be sure it has been
installed.
Configuring incomplete, errors occurred!
其中 eigen3 应该写成Eigen3
find_package(Eigen3 REQUIRED)
message("${EIGEN3_INCLUDE_DIR}")
include_directories( EIGEN3_INCLUDE_DIR )
–>
/usr/include/eigen3
- 分析
xx@ubuntu:/usr/lib/cmake/eigen3$ tree
.
├── Eigen3Config.cmake
├── Eigen3ConfigVersion.cmake
├── Eigen3Targets.cmake
└── UseEigen3.cmake
可见Eigen被正确安装,且提供了find_package查找方式。
- 2.1:find_package检索路径
三:变量
变量不需要声明, 有两种形式${variable} 和 variable, 前者是值引用,比较常见,后者直接引用,一般只用在赋值和条件判断中才会使用。
- 赋值:set(variable arg1 arg2 arg3 …)
1:自定义变量
2:内置变量
不动变量:
- CMAKE_SOURCE_DIR : 指定了CMakeLists.txt所在的目录
- PROJECT_SOURCE_DIR:指向构建工程的全路径
可以修改变量:
1)CMAKE_LIBRARY_OUTPUT_DIRECTORY :指定了cmake编译输出的东西应该放在什么地方
2)CMAKE_ARCHIVE_OUTPUT_DIRECTORY:
#set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
##:将build产生的exe文件和lib文件放到指定的目录中
四:头文件
五:库
六:常用
1: message :
- 例子:
message(FATAL_ERROR, "Fatal: this's fatal error")
message(WARNING, "Warn: this's warn msg")
message(STATUS, "Status: this's status msg")
message("This is message")
- 输出:(一般会用不同的颜色显示 比如在cmake-gui下 红色字体显示)
FATAL_ERROR,Fatal: this's fatal error
WARNING,Warn: this's warn msg
STATUS,Status: this's status msg
This is message
2:多行注释
- 语法格式
// *#[=*[注释内容]=*]*
备注:其中*号表示0个或者多个=,当然左边=号的数量要等于右边=的数量
- 例子
#[[这是多行注释!
这是多行注释!
这是多行注释!]]
七:语法
1:命令调用的参数
-
1.1: Bracket Argument
– 以[=*[
和]=*]
封闭参数内容, 其中*号表示0个或者多个=
– 当然左边=号的数量要等于右边=的数量
– 内容可以包含[/] -
例子
message([=[
This is the first line in a bracket argument with bracket length 1.
No \-escape sequences or ${variable} references are evaluated.
and can include [ content ] .
This is always one argument even though it contains a ; character.
The text does not end on a closing bracket of length 0 like .
It does end in a closing bracket of length 1.
]=])
- 输出
This is the first line in a bracket argument with bracket length 1.
No \-escape sequences or ${variable} references are evaluated.
and can include [ content ] .
This is always one argument even though it contains a ; character.
The text does not end on a closing bracket of length 0 like .
It does end in a closing bracket of length 1.
- 1.2: Quoted Argument
– 使用双引号""
来封闭参数内容
– 参数中不能包含"
和\
, 可以使用\
进行转移
– 参数中的${variable}
会被替换成相应的值
– 如果一行写不下,可以用\
进行换行 - 例子
message("This is a quoted argument containing multiple lines. \
This is always one argument even though it contains a ; character.
Both \\-escape sequences and ${variable} references are evaluated.
The text does not end on an escaped double-quote like \".
It does end in an unescaped double quote.
")
- 输出
This is a quoted argument containing multiple lines. This is always one argument even though it contains a ; character.
Both \-escape sequences and references are evaluated.
The text does not end on an escaped double-quote like ".
It does end in an unescaped double quote.
- 1.3: Unquoted Argument
– 不使用任何符号封闭参数内容;
– 参数中不可以包含空格()#” 、
,但可以用\
转义;
–;
会将参数内容分割成多个参数,可以用\
,可以用\
进行转义; - 例子
foreach(arg
NoSpace
Escaped\ Space
This;Divides;Into;Five;Arguments
Escaped\;Semicolon
)
message("${arg}")
endforeach()
- 输出
NoSpace
Escaped Space
This
Divides
Into
Five
Arguments
Escaped;Semicolon
2:注释
- 2.1:单行注释
# 单行注释
- 2.2: 多行注释
备注:可以放在代码中间
#[[This is a bracket comment.
It runs until the close bracket.]]
message("First Argument\n" #[[Bracket Comment]] "Second Argument")
3: 流程控制
- 3.1: 条件控制
if(expression)
# then section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
#...
elseif(expression2)
# elseif section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
#...
else(expression)
# else section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
#...
endif(expression)
//TODO
if(<constant>)
为true的constant:1, YES, ON, TRUE, Y, 或者非0数字;
为false的constant:0, NO, OFF, FALSE, N, IGNORE, NOTFOUND, 空字符串, 或者以-NOTFOUND为后缀的变量;
以上常量大小写不限;
if(variable | string)
variable被定义为非false的常量时为true,否则为false;
逻辑运算: NOT, AND, OR;
if(COMMAND command-name)
判断给定的名称是一个可以被调用的命令、宏或者函数;
if(TARGET target-name)
判断是否是一个已经(在子目录中)调用add_library, add_executable, add_custom_target生成的目标;
...
- 3.2: 循环控制
//TODO
foreach(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endforeach(loop_var)
对每个参数进行迭代
foreach(loop_var RANGE total)
foreach(loop_var RANGE start stop [step])
迭代生成的数字范围
例:
set(src_list a.c b.c d.c)
foreach(src ${src_list})
message(${src})
endforeach()
#生成从0到100的数字
foreach(num RANGE 100)
message(${num})
endforeach()
#生成从2到100的数字,间隔为2
foreach(num RANGE 2 100 2)
message(${num})
endforeach()
4:命令定义
- 4.1: 宏
//TODO
macro(<name> [arg1 [arg2 [arg3 ...]]])
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endmacro(<name>)
例:
# 求和
macro(sum out)
set(ret 0)
foreach(var ${ARGN})
math(EXPR ret "${ret}+${var}")
endforeach()
set(out ${ret})
endmacro()
sum(outRet 1 2 3 4 5)
message(${outRet})
使用${ARGC}获取传入的参数的数量;
使用${ARGV}获取传入的所有参数列表;
使用${ARGN}获取期望的参数列表(除去在定义宏时指定的参数列表)
使用${ARGV#}获取指定的参数,其中#为从0到${ARGC}的值,超出范围,行为未定义;
- 4.2: 函数
//TODO
function(<name> [arg1 [arg2 [arg3 ...]]])
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endfunction(<name>)
宏内部的变量在外部是可以访问的,而函数内部的变量则不行
其他
1:判断系统
IF(UNIX)
MESSAGE("UNIX:" ${UNIX})
ENDIF()
IF(WIN32)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE -DWIN32_LEAN_AND_MEAN -MD)
ELSEIF(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
ADD_DEFINITIONS(-DOSX)
ENDIF()
2:时间版本
备注:与cmake版本有关(低版本不支持,比如2.8.7 ,应该2.8.11以上,没验证)
#STRING(TIMESTAMP BUILD_TIMESTAMP UTC)
#MESSAGE(STATUS "Timestamp is ${BUILD_TIMESTAMP}")