cmake常用命令

目录:


常用指令

ADD_DEFINITIONS

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

ADD_DEPENDENCIES

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

ADD_EXECUTABLE

生成可执行程序

ADD_LIBRARY

创建库,动态和静态库

ADD_SUBDIRECTORY

添加子目录

ADD_TEST 与 ENABLE_TESTING 指令

ENABLE_TESTING 指令用来控制 Makefile 是否构建 test 目标,涉及工程所有目录。语 法很简单,没有任何参数,ENABLE_TESTING(),一般情况这个指令放在工程的主 CMakeLists.txt 中.
ADD_TEST 指令的语法是:
ADD_TEST(testname Exename arg1 arg2 ...)
testname 是自定义的 test 名称,Exename 可以是构建的目标文件也可以是外部脚本等 等。后面连接传递给可执行文件的参数。如果没有在同一个 CMakeLists.txt 中打开 ENABLE_TESTING()指令,任何 ADD_TEST 都是无效的。
比如我们前面的 Helloworld 例子,可以在工程主 CMakeLists.txt 中添加

ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main)
ENABLE_TESTING()

生成Makefile后,就可以运行make test来执行测试了。

AUX_SOURCE_DIRECTORY

基本语法是:
AUX_SOURCE_DIRECTORY(dir VARIABLE)
作用是发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表。因为目前 cmake 还不能自动发现新添加的源文件。
比如

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

你也可以通过后面提到的 FOREACH 指令来处理这个 LIST

CMAKE_MINIMUM_REQUIRED

其语法为

CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR]) 

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

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_VARIABLERETURN_VALUE 分别定义两个变量.
这个指令可以帮助你在 CMakeLists.txt 处理过程中支持任何命令,比如根据系统情况去
修改代码文件等等。
举个简单的例子,我们要在 src 目录执行 ls 命令,并把结果和返回值存下来。
可以直接在 src/CMakeLists.txt 中添加:

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

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

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)

INCLUDE

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

INCLUDE(file1 [OPTIONAL])
INCLUDE(module [OPTIONAL]) 

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

FIND指令

FIND_系列指令主要包含一下指令:

FIND_FILE

FIND_FILE(<VAR> name1 path1 path2 ...)
VAR 变量代表找到的文件全路径,包含文件名

FIND_LIBRARY

FIND_LIBRARY(<VAR> name1 path1 path2 ...)
VAR 变量表示找到的库全路径,包含库文件名

FIND_PATH

FIND_PATH(<VAR> name1 path1 path2 ...)
VAR 变量代表包含这个文件的路径, 不包含文件名

FIND_PROGRAM

FIND_PROGRAM(<VAR> name1 path1 path2 ...)
VAR 变量代表包含这个程序的全路径。

FIND_PACKAGE

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

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

FIND_LIBRARY(libX X11 /usr/lib) 
IF(NOT libX)
MESSAGE(FATAL_ERROR “libX not found”) 
ENDIF(NOT libX)

控制指令

IF指令

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)

WHILE指令

WHILE 指令的语法是:
WHILE(condition)
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
ENDWHILE(condition) 

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

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 指令,整个语句块才会得到真正的执行。

RF:
cmake practice 中文版

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容