cmake使用教程(实操版)(五)

一、cmake常用指令

本节会引入更多的cmake指令。

1、基本指令

(1)ADD_DEFINITIONS

向C/C++编译器添加-D定义,比如:
ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),参数之间用空格分隔。如果你的代码中定义了#ifdef ENABLE_DEBUG #endif,这个代码块就会生效。如果要添加其他的编译器开关,可以通过CMAKE_C_FLAGS变量和CMAKE_CXX_FLAGS变量设置。

(2)ADD_DEPENGENCIES

定义target依赖的其他的target,确保在编译本target之前,其他的target已经被构建。
ADD——DEPENDCIES(target-name depend-target1 depend-target2 …)

(3) ADD_EXECUTABLE、ADD_LIBRARY、ADD_SUBDIRECTORY见前面
(4) ADD_TEST与ENABLE_TESTING指令
ENABLE_TESTING

用来控制Makefile是否构建test目标,涉及工程所有目录。语法很简单,没有任何参数,ENABLE_TESTING(),一般情况这个指令放在工程的主CMakeLists.txt中。

ADD_TEST(testname Exename arg1 arg2 ...)

testname是自定义的test名称,Exename可以是构建的目标文件也可以是外部脚本等等。后面是传递给可执行文件的参数。如果没有在同一个CMakeLists.txt中打开ENABLE_TESTING()指令,任何ADD_TEST都是无效的。

举例:比如在t4中的主工程文件CMakeLists.txt中加入
在这里插入图片描述
cmake …
make test
在这里插入图片描述

(5) AUX_SOURCE_DIRECTORY

基本语法是:

AUX_SOURCE_DIRECTORY(dir VARIABLE)

发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表。

AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(main ${SRC_LIST})

后面提到的FOREACH指令来处理这个LIST

(6) CAMKE_MINIMUM_REQUIRED

其语法为

CAMKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR])

比如CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR)如果cmake版本小于2.5,则出现严重错误,整个过程终止。

(7) EXEC_PROGRAM

在CMakeLists.txt处理过程中执行命令,并不会在生成的Makefile中执行。具体语法为:

EXEC_PROGRAM(Executable [directory in which to run]
										[ARGS <arguments to executable>]
										[OUTPUT_VARIABLE <var>]
										[RETURN_VALUE <var>]

用于在指定的目录中运行某个程序,通过ARGS添加参数,如果要获取输出和返回值,可通过

OUTPUT_VARIABLE
RETURN_VALUE

分别定义两个变量。
这个指令可以帮助你在CAMKELists.txt处理过程中支持任何命令,比如根据系统情况取修改代码文件等等。

举例,在src目录执行ls命令,并把结果和返回值存下来。
可以在src/CMakeLists.txt中添加:

EXEC_PROGRAM(ls ARGS "*.c” OUTPUT_VARIABLE LS_OUTPUTRETURN_VALUE LS_RVALUE)
IF(not LS_RVALUE)
MESSAGE(STATUS "ls result:" ${LS_OUTPUT})
ENDIF(not LS_RVALUE)

在cmake生成Makefile的过程中,就会执行ls命令,如果返回0,则会说明成功执行,那么久输出ls *.c的结果。关于IF语句,后面的控制指令会提到。
在这里插入图片描述

(8)FILE指令

文件操作指令,基本语法为:

FILE(WRITE filename "message to write"... )
FILE(APPEND filename "message to write"... )
FILE(READ filename variable)
FILE(GLOB variable [RELATIVE path] [globbing
expressions]...)
FILE(GLOB_RECURSE variable [RELATIVE path]
[globbing expressions]...)
FILE(REMOVE [directory]...)
FILE(REMOVE_RECURSE [directory]...)
FILE(MAKE_DIRECTORY [directory]...)
FILE(RELATIVE_PATH variable directory file)
FILE(TO_CMAKE_PATH path result)
FILE(TO_NATIVE_PATH path result)

这里的语法都比较简单。

(9)INCLUDE指令

用来载入CMakeLists.txt文件,也用于载入预定义的cmake模块。

INCLUDE(file1 [optional])
INCLUDE(module [OPTIAONAL])

OPTIONAL参数的作用时文件不存在也不会产生错误。
你可以指定一再入一个文件,如果定义的是一个模块,那么将在CAMKE_MODULE_PATH中搜索这个模块并载入。载入的内容将在处理到INCLUDE语句是直接执行。

2、INSTALL命令

参见前面。

3、FIND_指令

FIND_系列指令主要包含以下的命令:

(1) FIND_FILE(<VAR> name1 path1 path2 …)

VAR变量代表找到的文件全路径,包含文件名

(2) FIND_LIBRARY(<VAR> name1 path1 path2 …)

VAR变量表示找到的库全路径,包含库文件

(3) FIND_PATH(<VAR> name1 path1 path2 …)

VAR变量代表包含这个文件的路径。

(4) FIND_PROGRAM(<VAR> name1 path1 path2 …)

VAR变量代表包含这个程序的全路径。

(5)FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets …]])

用来有调用预定义在CAMEK_MODULE_PATH下的FIND<name>.cmake模块,你也可以自己定义FInd<name>模块,通过SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录中供工程使用,在后面的章节会详细介绍FIND_PACKAGE的使用方法和FIND模块的编写。

4、控制指令

1,IF 指令,基本语法为:
IF(expression)
# THEN section.
COMMAND1(ARGS ...)COMMAND2(ARGS ...)
...
ELSE(expression)
# ELSE section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDIF(expression)

另外一个指令是 ELSEIF,总体把握一个原则,凡是出现 IF 的地方一定要有对应的
ENDIF.出现 ELSEIF 的地方,ENDIF 是可选的。
表达式的使用方法如下:

IF(var)#如果变量不是:空,0,N, NO, OFF, FALSE, NOTFOUND 或<var>_NOTFOUND 时,表达式为真。
IF(NOT var )#与上述条件相反。
IF(var1 AND var2)#当两个变量都为真是为真。
IF(var1 OR var2)#当两个变量其中一个为真时为真。
IF(COMMAND cmd)#当给定的 cmd 确实是命令并可以调用是为真。
IF(EXISTS dir)或者 IF(EXISTS file)#当目录名或者文件名存在时为真。
IF(file1 IS_NEWER_THAN file2)#当 file1 比 file2 新,或者 file1/file2 其中有一个不存在时为真,文件名请使用完整路径。
IF(IS_DIRECTORY dirname)#当 dirname 是目录时,为真。
IF(variable MATCHES regex)
IF(string MATCHES regex)#当给定的变量或者字符串能够匹配正则表达式 regex 时为真。比如:
IF("hello" MATCHES "ell")
    MESSAGE("true")
ENDIF("hello" MATCHES "ell")IF(variable LESS number)
IF(string LESS number)
IF(variable GREATER number)
IF(string GREATER number)
IF(variable EQUAL number)
IF(string EQUAL number)
#数字比较表达式
IF(variable STRLESS string)
IF(string STRLESS string)
IF(variable STRGREATER string)
IF(string STRGREATER string)
IF(variable STREQUAL string)
IF(string STREQUAL string)
#按照字母序的排列进行比较.
IF(DEFINED variable)#如果变量被定义,为真。
一个小例子,用来判断平台差异:
IF(WIN32)
MESSAGE(STATUS “This is windows.”)
#作一些 Windows 相关的操作
ELSE(WIN32)
MESSAGE(STATUS “This is not windows”)
#作一些非 Windows 相关的操作
ENDIF(WIN32)

上述代码用来控制在不同的平台进行不同的控制,但是,阅读起来却并不是那么舒服,
ELSE(WIN32)之类的语句很容易引起歧义。
这就用到了我们在“常用变量”一节提到的 CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 开
关。

SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

这时候就可以写成:

IF(WIN32)
ELSE()
ENDIF()如果配合 ELSEIF 使用,可能的写法是这样:
IF(WIN32)
#do something related to WIN32
ELSEIF(UNIX)
#do something related to UNIX
ELSEIF(APPLE)
#do something related to APPLE
ENDIF(WIN32)
2、WHILE

WHILE 指令的语法是:

WHILE(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDWHILE(condition)

其真假判断条件可以参考 IF 指令。

3、FOREACH

FOREACH 指令的使用方法有三种形式:
1,列表

FOREACH(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDFOREACH(loop_var)

像我们前面使用的 AUX_SOURCE_DIRECTORY 的例子

AUX_SOURCE_DIRECTORY(. SRC_LIST)
FOREACH(F ${SRC_LIST})
MESSAGE(${F})
ENDFOREACH(F)

2,范围

FOREACH(loop_var RANGE total)
ENDFOREACH(loop_var)
#从 0 到 total 以1为步进举例如下:
FOREACH(VAR RANGE 10)
  MESSAGE(${VAR})
ENDFOREACH(VAR)

最终得到的输出是:
0 1 2 3 4 5 6 7 8 9
10

3,范围和步进

FOREACH(loop_var RANGE start stop [step])
ENDFOREACH(loop_var)

从 start 开始到 stop 结束,以 step 为步进,
举例如下

FOREACH(A RANGE 5 15 3)
MESSAGE(${A})
ENDFOREACH(A)

最终得到的结果是:
5 8
11
14
这个指令需要注意的是,知道遇到 ENDFOREACH 指令,整个语句块才会得到真正的执行

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值