目录
- CMake 语法
- Hello, World
- 基本语法
- 文件编码-Encoding
- 注释-Comments
- 单行注释
- 多行注释
- 字符串
- 设置变量-set
- 取消设置变量-unset
- 变量引用-${var}
- 条件表达式-if
- 关键字
- 结构
- 真值
- 假值
- 逻辑表达式
- 判断函数或宏的返回值
- 判断编译目标是否存在
- 文件和目录相关
- 值比较
- 字符串比较
- 版本比较
- 判断变量是否定义
- 正则匹配
- 循环-loop
- foreach
- while
- continue & break
- 函数/宏-function/macro
- 函数-function
- 宏-macro
- 作用域
- 创建executable/library
- add_executable
- add_library
- 链接库
- 名称前缀/后缀
- 链接-link
- link_libraries
- target_link_libraries
- MSVC编译器设置源文件为UTF-8编码
- 设置C++版本
- 平台判断
- find_package
- install
- message
CMake 语法
Hello, World
cmake_minimum_required(VERSION 3.5) # 指定CMake的版本
project(hello-world) # 项目名称
add_executable(hello ) # 创建一个可执行程序
基本语法
文件编码-Encoding
官方说明文档:文件编码
- 在3.0以下的版本,CMake文件必须使用7-bit的ASCII编码,在3.0以后可以使用UTF-8编码
- 文件的换行符必须使用
\n
或\r\n
注释-Comments
官方说明文档:Comments1
官方说明文档:Comments2
单行注释
test # comment
多行注释
# 最简单的多行注释
test #[[comment]]
# 注释两边的`=`个数要相等
test #[={len}[comment]={len}]
字符串
官方说明文档:字符串
-
字符串的格式为
"string"
-
对于多行字符串,可以在行尾添加
\
来忽略换行符### Example-1 message("12 34") # 12 # 34 ### Example-2 message("12\ 34") # 1234
-
使用
[={len}[string]={len}]
来可以禁止字符串转义;左右两边的=
个数需要相等### Example-1 message([=[string\n]=]) # string\n ### Example-2 message("string\n") # string # ### Example-3 message([==[string]=]) # ERROR: 左右两边的=个数不相等 ### Example-4 message([=[string]==]) # ERROR: 左右两边的=个数不相等 ### Example-5 message([==========[string]==========]) # OK: 左右两边的=个数相等 # string
设置变量-set
官方说明文档:设置变量
set(<variable> <value> [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])
-
设置普通变量
set(var0 "string")
-
设置数组
set(arr0 "item0;item0;item2") set(arr1 item0 item1 item2) set(arr2 ${arr0} ${arr1}) set(arr3 "${arr0};${arr1}") # 使用'\ '来转义空格 set(arr4 item0 item1\ item2) foreach(item ${arr4}) message(${item}) endforeach() # item0 # item1 item2 # 使用'\;'来转义分号 set(arr5 "item0;item0\;item2") foreach(item ${arr5}) message(${item}) endforeach() # item0 # item1;item2
-
设置环境变量
set($ENV{TEST_ENV_VARIABLE} 233)
取消设置变量-unset
官方说明文档:取消设置变量
unset(<variable> [CACHE | PARENT_SCOPE])
- 将变量、缓存变量或环境变量改为未定义状态
变量引用-${var}
官方说明文档:变量引用
-
变量通过
${}
来引用set(var 233) message(${var}) # 233
-
变量可以嵌套引用
set(inner 666) set(outer_233 233) set(outer_666 666) set(id "bb") set(outer_666_aa "666 aa") set(outer_666_bb "666 bb") message(${outer_${inner}}) # 666 message(${outer_${inner}_${id}}) ## 666 bb
-
变量可以在引号表达式中使用
set(var 233) message("current var is ${var}") # 233
-
使用环境变量,通过
$ENV{环境变量名}
即可获取message("$ENV{PATH}") # LIKE: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin;......
条件表达式-if
官方说明文档:条件表达式
关键字
if()/elseif()/else()/endif()
结构
if(expression)
[statement]
elseif(expression)
[statement]
elseif(expression)
[statement]
else()
[statement]
endif()
真值
-
1
、ON
、YES
、TRUE
,Y
或非0数字
- 不区分大小写
假值
-
0
、OFF
、NO
、FALSE
、N
、IGNORE
、NOTFOUND
、空字符串
或以-NOTFOUND结尾的变量
- 不区分大小写
逻辑表达式
-
NOT
:逻辑非if (NOT <expr>)
-
AND
:逻辑与if (<expr0> AND <expr1>)
-
OR
:逻辑或if (<expr0> OR <expr1>)
判断函数或宏的返回值
-
如果返回值为真值,则表达式为真
if (COMMAND <command>)
判断编译目标是否存在
-
如果目标是通过
add_executable
、add_library
或add_custom_target
来创建的,则表达式为真if (TARGET <target>)
文件和目录相关
-
判断文件或者目录是否存在:如果文件或者目录存在,则表达式为真
if (EXISTS path-to-file-or-directory)
-
比较两个文件哪个更新:如果
file1
比file2
更新,则表达式为真if (file1 IS_NEWER_THAN file2)
-
判断目标是不是目录
if (IS_DIRECTORY path-to-directory)
-
判断目标是不是符号链接
if (IS_SYMLINK file-name)
-
判断路径是不是绝对路径
if (IS_ABSOLUTE path)
值比较
-
小于,variable或string必须能解析成数字才可以比较
if (<variable|string> LESS <variable|string>)
-
大于,variable或string必须能解析成数字才可以比较
if (<variable|string> GREATER <variable|string>)
-
等于,variable或string必须能解析成数字才可以比较
if (<variable|string> EQUAL <variable|string>)
字符串比较
-
小于,按照字典序比较
if (<variable|string> STRLESS <variable|string>)
-
大于,按照字典序比较
if (<variable|string> STRGREATER <variable|string>)
-
等于,按照字典序比较
if (<variable|string> STREQUAL <variable|string>)
版本比较
-
版本号格式
major[.minor[.patch[.tweak]]]
-
小于
if (<variable|string> VERSION_LESS <variable|string>)
-
大于
if (<variable|string> VERSION_GREATER <variable|string>)
-
等于
if (<variable|string> VERSION_EQUAL <variable|string>)
判断变量是否定义
-
判断变量是否定义,
macro
的参数不是变量if (DEFINED <variable>)
正则匹配
-
判断变量或字符串是否匹配正则表达式
if (<variable|string> MATCHES regex)
循环-loop
foreach
官方说明文档:foreach
-
类型1:参数可以是元素或者是数组
foreach(loop_var arg1 arg2 ...) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... endforeach(loop_var)
-
类型2:for range
# 从start开始,到stop,每次增加step步,start,stop,step都是整数 foreach(loop_var RANGE start stop [step]) # total是一个整数,相当于foreach(loop_var RANGE 0 total 1) foreach(loop_var RANGE total)
-
类型3:for in lists/items
foreach(loop_var IN [LISTS [list1 [...]]] [ITEMS [item1 [...]]])
-
foreach(loop_var IN LISTS list1 list2 ...)
可以用foreach(loop_var ${list1} ${list2} ...)
代替 -
foreach(loop_var IN ITEMS item1 item2 ...)
可以用foreach(loop_var ${item1} ${item2} ...)
代替
-
while
官方说明文档:while
while(condition) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... endwhile(condition)
continue & break
官方说明文档:continue
官方说明文档:break
continue() break()
函数/宏-function/macro
函数-function
官方说明文档:函数
function(<name> [<arg1> ...]) <commands> endfunction()
- ARGC:输入的参数个数
- ARGN:输入的参数
- ARGV0,ARGV1…ARGVN:参数
function是独立的作用域,在function内定义的变量外部是访问不了的,需要通过
set(var PARENT_SCOPE)
来向外暴露变量
宏-macro
官方说明文档:宏
macro(<name> [<arg1> ...]) <commands> endmacro()
- 宏的参数不能通过
ARGC
、ARGN
和ARGV{IDX}
来获取 - 宏内定义的变量的作用域在父级
作用域
官方说明文档:作用域
- 全局层:定义在cache中,整个项目可见
- 目录层:在当前内
- 函数层:定义在
function
内,函数内可见 - 全局层<目录层<函数层;会优先使用当前层内变量,如果没有,或到父级找,但被修改的变量不会先父级传递
创建executable/library
add_executable
官方说明文档:add_executable
# 创建可执行程序 add_executable(<name> [source1] [source2 ...])
add_library
官方说明文档:add_library
# 创建动态库/静态库 add_library(<name> [STATIC|SHARED|MODULE] [source1] [source2 ...]) # 从外部导入动态库/静态库 add_library(<name> <SHARED|STATIC|MODULE|OBJECT|UNKNOWN> IMPORTED [GLOBAL])
链接库
-
导入动态链接库(Windows)
set(target "example") add_library(${target} SHARED IMPORTED) set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties(${target} PROPERTIES IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/path/to/" IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/path/to/" ) set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(${target} PROPERTIES IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/path/to/" IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/path/to/" )
-
导入静态链接库(Windows)
set(target "example") add_library(${target} SHARED IMPORTED) set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties(${target} PROPERTIES IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/path/to/" ) set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(${target} PROPERTIES IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/path/to/" )
-
导入动态链接库(Linux/Unix)
set(target "example") add_library(${target} SHARED IMPORTED) set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties(${target} PROPERTIES IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/path/to/" ) set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(${target} PROPERTIES IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/path/to/" )
-
导入静态链接库(Linux/Unix)
set(target "example") add_library(${target} SHARED IMPORTED) set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties(${target} PROPERTIES IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/path/to/" ) set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(${target} PROPERTIES IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/path/to/" )
名称前缀/后缀
-
设置输出可执行程序/库的名称前缀/后缀
set_target_properties(target1 target2 ... PROPERTIES prop1 value1 prop2 value2 ...)
set_target_properties(${module_name} PROPERTIES PREFIX "lib" # 前缀 <CONFIG>_POSTFIX "d" # 后缀,可以分DEBUG/RELEASE版本 )
链接-link
link_libraries
官方说明文档:link_libraries
link_libraries([item1 [item2 [...]]] [[debug|optimized|general] <item>] ...)
target_link_libraries
官方说明文档:target_link_libraries
target_link_libraries(<target> ... <item>... ...)
MSVC编译器设置源文件为UTF-8编码
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/source-charset:utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/source-charset:utf-8>")
设置C++版本
# C++11/C++0x
set(CMAKE_CXX_STANDARD 11)
if (CMAKE_VERSION VERSION_LESS "3.1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif ()
# C++14/C++1y
set(CMAKE_CXX_STANDARD 14)
if (CMAKE_VERSION VERSION_LESS "3.1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
endif ()
# C++17/C++1z
set(CMAKE_CXX_STANDARD 17)
if (CMAKE_VERSION VERSION_LESS "3.1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z")
endif ()
# C++20/C++2a
set(CMAKE_CXX_STANDARD 20)
if (CMAKE_VERSION VERSION_LESS "3.1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a")
endif ()
平台判断
if(WIN32)
add_definitions(-DPLATFORM_WINDOWS=1)
set(PLATFORM_WINDOWS 1)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
elseif(APPLE)
if(IOS)
add_definitions(-DPLATFORM_IOS=1)
set(PLATFORM_IOS 1)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_definitions(-DPLATFORM_OSX=1)
set(PLATFORM_OSX 1)
endif()
elseif(ANDROID)
add_definitions(-DPLATFORM_ANDROID=1)
set(PLATFORM_ANDROID 1)
elseif(UNIX)
add_definitions(-DPLATFORM_LINUX=1)
set(PLATFORM_LINUX 1)
execute_process(COMMAND bash "-c" "cat /etc/*-release" RESULT_VARIABLE rv OUTPUT_VARIABLE out)
if (${rv})
message(FATAL_ERROR "command execute error")
else()
if (out MATCHES ".*Ubuntu.*")
add_definitions(-DPLATFORM_UBUNTU=1)
set(PLATFORM_UBUNTU 1)
elseif(out MATCHES ".*CentOS.*")
add_definitions(-DPLATFORM_CENTOS=1)
set(PLATFORM_CENTOS 1)
else()
message("Unknown Linux Branch")
endif()
endif()
else()
add_definitions(-DPLATFORM_UNKNOWN=1)
set(PLATFORM_UNKNOWN 1)
message(WARNING "Unknown Platform")
message(WARNING "Unknown Platform")
message(WARNING "Unknown Platform")
endif()
find_package
官方说明文档:find_package
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [components...]] [OPTIONAL_COMPONENTS components...] [NO_POLICY_SCOPE])
-
OpenCV
# - OpenCV_LIBS : The list of libraries to link against. # - OpenCV_INCLUDE_DIRS : The OpenCV include directories. # - OpenCV_COMPUTE_CAPABILITIES : The version of compute capability # - OpenCV_VERSION : The version of this OpenCV build: "3.4.1" # - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION: "3" # - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION: "4" # - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION: "1" find_package(OpenCV 3.0 REQUIRED COMPONENTS core imgproc imgcodecs) if (OpenCV_FOUND) include_directories(${OpenCV_INCLUDE_DIRS}) target_link_libraries(target ${OpenCV_LIBS}) endif()
install
官方说明文档:install
message
官方说明文档:message
message([<mode>] "message to display" ...)
-
FATAL_ERROR
:错误,会停止配置和生成 -
SEND_ERROR
:错误,继续处理,但不会生成 -
WARNING
:警告 -
NOTICE
:默认 -
STATUS
:状态