一、CMake基本语法
编写的CMakeLists.txt需要符合一定的语法规则,它主要由CMake命令组成。
1)注释的语法:
在CMake中注释使用#字符开始到此行结束。
2)CMake命令:
命令不区分大小写(参数会区分大小写),命令由命令、参数列表组成,参数之间使用空格进行分隔。使用一对双引号包括的字符串认为是一个参数。命令可以是一个内置命令(例如:project,add_executable等),也可以是一个用户定义的宏(macro)或者函数(function)。
3)数据类型:
CMake的基本数据类型是字符串,一组字符串在一起称为列表(list),例如:
1 # 通过 set 命令构建一个 listVAR 2 set(VAR a b c)
使用语法 ${VariableName} 来访问名字为 VariableName 的变量的值(变量名区分大小写)。需要注意的是,即使在字符串中也可以使用${VariableName} 来访问变量的值:
1 set(VAR a b c) 2 # 输出 VAR = a;b;c 3 message("VAR = ${VAR}")
使用语法 $ENV{VariableName} 来访问环境变量的值(ENV{VariableName} 则表示环境变量本身)
1 # 输出环境变量 PATH 的值 2 message($ENV{PATH})
4)条件控制和循环结构
条件控制命令为 if 命令
1 if(expression) 2 #... 3 elseif(expression2) 4 #... 5 else() 6 #... 7 endif()
对于 if(string) 来说:
如果 string 为(不区分大小写)1、ON、YES、TRUE、Y、非 0 的数则表示真
如果 string 为(不区分大小写)0、OFF、NO、FALSE、N、IGNORE、空字符串、以 -NOTFOUND 结尾的字符串则表示假
如果 string 不符合上面两种情况,则 string 被认为是一个变量的名字。变量的值为第二条所述的各值则表示假,否则表示真。
1 # 此策略(Policy)在 CMake2.8.0 才被引入 2 # 因此这里需要指定最低 CMake 版本为 2.8 3 cmake_minimum_required(VERSION 2.8) 4 set(YES 0) 5 6 # 输出 True 7 if(YES) 8 message(True) 9 else() 10 message(False) 11 endif() 12 13 # 输出 False 14 if(${YES}) 15 message(True) 16 else() 17 message(False) 18 endif()
表达式中可以包含操作符,操作符包括:
一元操作符,例如:EXISTS、COMMAND、DEFINED 等
二元操作符,例如:EQUAL、LESS、GREATER、STRLESS、STRGREATER 等
NOT(非操作符)
AND(与操作符)、OR(或操作符)
操作符优先级:一元操作符 > 二元操作符 > NOT > AND、OR
常用操作符介绍:
1 if(NOT expression) 2 //为真的前提是 expression 为假 3 if(expr1 AND expr2) 4 //为真的前提是 expr1 和 expr2 都为真 5 if(expr1 OR expr2) 6 //为真的前提是 expr1 或者 expr2 为真 7 if(COMMAND command-name) 8 //为真的前提是存在 command-name 命令、宏或函数且能够被调用 9 if(EXISTS name) 10 //为真的前提是存在 name 的文件或者目录(应该使用绝对路径) 11 if(file1 IS_NEWER_THAN file2) 12 //为真的前提是 file1 比 file2 新或者 file1、file2 中有一个文件不存在(应该使用绝对路径) 13 if(IS_DIRECTORY directory-name) 14 //为真的前提是 directory-name 表示的是一个目录(应该使用绝对路径) 15 if(variable|string MATCHES regex) 16 //为真的前提是变量值或者字符串匹配 regex 正则表达式 17 if(variable|string LESS variable|string) 18 if(variable|string GREATER variable|string) 19 if(variable|string EQUAL variable|string) 20 //为真的前提是变量值或者字符串为有效的数字且满足小于(大于、等于)的条件 21 if(variable|string STRLESS variable|string) 22 if(variable|string STRGREATERvariable|string) 23 if(variable|string STREQUALvariable|string) 24 //为真的前提是变量值或者字符串以字典序满足小于(大于、等于)的条件 25 if(DEFINED variable) 26 //为真的前提是 variable 表示的变量被定义了。
foreach 循环范例:
1 set(VAR a b c) 2 foreach(f ${VAR}) 3 message(${f}) 4 endforeach()
while 循环范例:
1 set(VAR 5) 2 while(${VAR} GREATER 0) 3 message(${VAR}) 4 math(EXPR VAR "${VAR} - 1") 5 endwhile()
5)函数和宏定义
函数会为变量创建一个局部作用域,而宏则使用全局作用域。范例:
1 # 定义一个宏 hello 2 macro(hello MESSAGE) 3 message(${MESSAGE}) 4 endmacro() 5 6 # 调用宏 hello 7 hello("hello world") 8 # 定义一个函数 hello 9 function(hello MESSAGE) 10 message(${MESSAGE}) 11 endfunction()
函数和宏可以通过命令 return() 返回,但是函数和宏的返回值必须通过参数传递出去。例如:
1 cmake_minimum_required(VERSION 2.8) 2 function(get_func RESULT) 3 #RESULT 的值为实参的值,因此需要使用 ${RESULT} 4 #这里使用 PARENT_SCOPE 是因为函数会构建一个局部作用域 5 set(${RESULT} "Hello Function" PARENT_SCOPE) 6 endfunction() 7 8 macro(get_macro RESULT) 9 set(${RESULT} "Hello Macro") 10 endmacro() 11 12 get_func(V1) 13 # 输出 Hello Function 14 message(${V1}) 15 16 get_macro(V2) 17 # 输出 Hello Macro 18 message(${V2})
6)字符串的一些问题
字符串可跨行且支持转移字符,例如:
1 set(VAR "hello 2 world") 3 4 # 输出结果为: 5 # ${VAR} = hello 6 # world 7 message("${VAR} = ${VAR}")
二、cmake常用命令
cmake有很多命令,这里我们只对一些常用的命令进行介绍,如果碰到不常见的一些命令,或者有什么需要的命令可以去这里查询:https://cmake.org/cmake/help/v2.8.8/cmake.html#section_Commands
1)project 命令
命令语法:project(<projectname> [languageName1 languageName2 … ] )
命令简述:用于指定项目的名称
使用范例:project(Main)
2)cmake_minimum_required命令
命令语法:cmake_minimum_required(VERSION major[.minor[.patch[.tweak]]][FATAL_ERROR])
命令简述:用于指定需要的 CMake 的最低版本
使用范例:cmake_minimum_required(VERSION 2.8)
3)aux_source_directory命令
命令语法:aux_source_directory(<dir> <variable>)
命令简述:用于将 dir 目录下的所有源文件的名字保存在变量 variable 中
使用范例:aux_source_directory(. DIR_SRCS)
4)add_executable 命令
命令语法:add_executable(<name> [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL] source1 source2 … sourceN)
命令简述:用于指定从一组源文件 source1 source2 … sourceN 编译出一个可执行文件且命名为 name
使用范例:add_executable(Main ${DIR_SRCS})
5)add_library 命令
命令语法:add_library([STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1source2 … sourceN)
命令简述:用于指定从一组源文件 source1 source2 … sourceN 编译出一个库文件且命名为 name(默认为静态库)
使用范例:add_library(Lib ${DIR_SRCS})
6)add_dependencies 命令
命令语法:add_dependencies(target-name depend-target1 depend-target2 …)
命令简述:用于指定某个目标(可执行文件或者库文件)依赖于其他的目标。这里的目标必须是 add_executable、add_library、add_custom_target 命令创建的目标
7)add_subdirectory 命令
命令语法:add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
命令简述:用于添加一个需要进行构建的子目录
使用范例:add_subdirectory(Lib)
8)target_link_libraries命令
命令语法:target_link_libraries(<target> [item1 [item2 […]]][[debug|optimized|general] ] …)
命令简述:用于指定 target 需要链接 item1 item2 …。这里 target 必须已经被创建,链接的 item 可以是已经存在的 target(依赖关系会自动添加)
使用范例:target_link_libraries(Main Lib)
9)set 命令
命令语法:set(<variable> <value> [[CACHE <type><docstring> [FORCE]] | PARENT_SCOPE])
命令简述:用于设定变量 variable 的值为 value。如果指定了 CACHE 变量将被放入 Cache(缓存)中。
使用范例:set(ProjectName Main)
10)unset 命令
命令语法:unset(<variable> [CACHE])
命令简述:用于移除变量 variable。如果指定了 CACHE 变量将被从 Cache 中移除。
使用范例:unset(VAR CACHE)
11)message 命令
命令语法:message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] “message todisplay”…)
命令简述:用于输出信息
使用范例:message(“Hello World”)
12)include_directories 命令
命令语法:include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)
命令简述:用于设定目录,这些设定的目录将被编译器用来查找 include 文件
使用范例:include_directories(${PROJECT_SOURCE_DIR}/lib)
13)find_path 命令
命令语法:find_path(<VAR> name1 [path1 path2 …])
命令简述:用于查找包含文件 name1 的路径,如果找到则将路径保存在 VAR 中(此路径为一个绝对路径),如果没有找到则结果为 <VAR>-NOTFOUND。默认的情况下,VAR 会被保存在 Cache 中,这时候我们需要清除 VAR 才可以进行下一次查询(使用 unset 命令)。
使用范例:
find_path(LUA_INCLUDE_PATH lua.h${LUA_INCLUDE_FIND_PATH})
if(NOT LUA_INCLUDE_PATH)
message(SEND_ERROR "Header file lua.h not found")
endif()
14)find_library 命令
命令语法:find_library(<VAR> name1 [path1 path2 …])
命令简述:用于查找库文件 name1 的路径,如果找到则将路径保存在 VAR 中(此路径为一个绝对路径),如果没有找到则结果为 <VAR>-NOTFOUND。一个类似的命令 link_directories 已经不太建议使用了
15)add_definitions 命令
命令语法:add_definitions(-DFOO -DBAR …)
命令简述:用于添加编译器命令行标志(选项),通常的情况下我们使用其来添加预处理器定义
使用范例:add_definitions(-D_UNICODE -DUNICODE)
16)execute_process 命令
命令语法:
execute_process(COMMAND <cmd1>[args1...]]
[COMMAND <cmd2>[args2...] [...]]
[WORKING_DIRECTORY<directory>]
[TIMEOUT <seconds>]
[RESULT_VARIABLE<variable>]
[OUTPUT_VARIABLE<variable>]
[ERROR_VARIABLE<variable>]
[INPUT_FILE <file>]
[OUTPUT_FILE <file>]
[ERROR_FILE <file>]
[OUTPUT_QUIET]
[ERROR_QUIET]
[OUTPUT_STRIP_TRAILING_WHITESPACE]
[ERROR_STRIP_TRAILING_WHITESPACE])
命令简述:用于执行一个或者多个外部命令。每一个命令的标准输出通过管道转为下一个命令的标准输入。WORKING_DIRECTORY 用于指定外部命令的工作目录,RESULT_VARIABLE 用于指定一个变量保存外部命令执行的结果,这个结果可能是最后一个执行的外部命令的退出码或者是一个描述错误条件的字符串,OUTPUT_VARIABLE 或者 ERROR_VARIABLE 用于指定一个变量保存标准输出或者标准错误,OUTPUT_QUIET 或者 ERROR_QUIET 用于忽略标准输出和标准错误。
使用范例:execute_process(COMMAND ls)
18)file 命令
命令简述:此命令提供了丰富的文件和目录的相关操作(这里仅说一下比较常用的)
使用范例:
# 目录的遍历
# GLOB 用于产生一个文件(目录)路径列表并保存在variable 中
# 文件路径列表中的每个文件的文件名都能匹配globbing expressions(非正则表达式,但是类似)
# 如果指定了 RELATIVE 路径,那么返回的文件路径列表中的路径为相对于 RELATIVE 的路径
# file(GLOB variable [RELATIVE path][globbing expressions]...)
# 获取当前目录下的所有的文件(目录)的路径并保存到 ALL_FILE_PATH 变量中
file(GLOB ALL_FILE_PATH ./*)
# 获取当前目录下的 .h 文件的文件名并保存到ALL_H_FILE 变量中
# 这里的变量CMAKE_CURRENT_LIST_DIR 表示正在处理的 CMakeLists.txt 文件的所在的目录的绝对路径(2.8.3 以及以后版本才支持)
file(GLOB ALL_H_FILE RELATIVE${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/*.h)
CMake常用变量
UNIX 如果为真,表示为 UNIX-like 的系统,包括 AppleOS X 和 CygWin
WIN32 如果为真,表示为 Windows 系统,包括 CygWin
APPLE 如果为真,表示为 Apple 系统
CMAKE_SIZEOF_VOID_P 表示 void* 的大小(例如为 4 或者 8),可以使用其来判断当前构建为 32 位还是 64 位
CMAKE_CURRENT_LIST_DIR 表示正在处理的CMakeLists.txt 文件的所在的目录的绝对路径(2.8.3 以及以后版本才支持)
CMAKE_ARCHIVE_OUTPUT_DIRECTORY 用于设置 ARCHIVE 目标的输出路径
CMAKE_LIBRARY_OUTPUT_DIRECTORY 用于设置 LIBRARY 目标的输出路径
CMAKE_RUNTIME_OUTPUT_DIRECTORY 用于设置 RUNTIME 目标的输出路径
更多内容常见:https://www.cnblogs.com/never--more/p/6921837.html