cmake学习笔记

一、cmake常用变量和常用环境变量

1、cmake变量引用形式:

cmake使用${}进行变量的引用,在if语句中直接使用变量名而不需要通过${}取值。


2、cmake自定义变量的方式:

分为显式定义和隐式定义,例如PROJECT指令,会隐式定义<projectname>_BINARY_DIR和<projectname>_SOURCE_DIR两个变量

显式定义使用SET指令,例如: SET(HELLO_SRC main.c),则可以使用${HELLO_SRC}来引用此变量


3、cmake常用变量:

1) CMAKE_BINARY_DIR

    PROJECT_BINARY_DIR

    <projectname>_BINARY_DIR

此三个变量指代的内容是一致的,如果是in source编译,指得就是工程顶层目录,如果是out-of-source编译,指的是工程编译发生的目录。


2) CMAKE_SOURCE_DIR

    PROJECT_SOURCE_DIR

    <projectname>_SOURCE_DIR

这三个变量指代的内容也是一致的,都是工程顶层目录


3) CMAKE_CURRENT_SOURCE_DIR

    指当前处理的CMakeLists.txt所在的路径


4) CMAKE_CURRENT_BINARY_DIR

    如果是in-source编译,它跟CMAKE_CURRENT_SOURCE_DIR一致,如果是out-ofsource编译,他指的是target编译目录。


5) CMAKE_CURRENT_LIST_FILE

    调用这个变量的CMakeLists.txt的完整路径


6) CMAKE_CURRENT_LIST_LINE

    这个变量所在的行


7) CMAKE_MODULE_PATH

    定义自己的cmake模块所在的路径。如果你的工程比较复杂,有可能会自己编写一些cmake模块,这些cmake模块是随你的工程发布的,为了让cmake在处理CMakeLists.txt时找到这些模块,你需要通过SET指令,将自己的cmake模块路径设置一下。
比如
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
这时候你就可以通过INCLUDE指令来调用自己的模块了。


8) EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH

    定义目标二进制可执行文件的存放位置


9) PROJECT_NAME

    通过PROJECT指令定义的项目名称。


4、cmake调用环境变量的方式

    使用$ENV{NAME}指令就可以调用系统的环境变量了。
    比如
    MESSAGE(STATUS “HOME dir: $ENV{HOME}”)
    设置环境变量的方式是:
    SET(ENV{变量名} 值)


    CMAKE_INCLUDE_CURRENT_DIR
自动添加CMAKE_CURRENT_BINARY_DIR和CMAKE_CURRENT_SOURCE_DIR到当前处理
的CMakeLists.txt。相当于在每个CMakeLists.txt加入:
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR})


5、系统信息

1,CMAKE_MAJOR_VERSION,CMAKE主版本号,比如2.4.6中的2
2,CMAKE_MINOR_VERSION,CMAKE次版本号,比如2.4.6中的4
3,CMAKE_PATCH_VERSION,CMAKE补丁等级,比如2.4.6 中的6
4,CMAKE_SYSTEM,系统名称,比如Linux-2.6.22
5,CMAKE_SYSTEM_NAME,不包含版本的系统名,比如Linux
6,CMAKE_SYSTEM_VERSION,系统版本,比如2.6.22
7,CMAKE_SYSTEM_PROCESSOR,处理器名称,比如i686.
8,UNIX,在所有的类UNIX平台为TRUE,包括OS X和cygwin
9,WIN32,在所有的win32平台为TRUE,包括cygwin


二、cmake常用指令

1、基本指令

1) ADD_DEFINITIONS

向C/C++编译器添加-D定义,比如:
ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),参数之间用空格分割。
如果你的代码中定义了#ifdef ENABLE_DEBUG #endif,这个代码块就会生效。


2) ADD_DEPENDENCIES

定义target依赖的其他target,确保在编译本target之前,其他的target已经被构建。

ADD_DEPENDENCIES(target-name depend-target1 depend-target2 ...)


3) ADD_EXECUTABLE


4) ADD_LIBRARY


5) ADD_SUBDIRECTORY


6) 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都是无效的。


7) AUX_SOURCE_DIRECTORY

基本语法是:
AUX_SOURCE_DIRECTORY(dir VARIABLE)

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

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


8) CMAKE_MINIMUM_REQUIRED

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


9) EXEC_PROGRAM
在CMakeLists.txt处理过程中执行命令,并不会在生成的Makefile中执行。


10) FILE指令


11) INCLUDE指令,

用来载入CMakeLists.txt文件,也用于载入预定义的cmake模块.
INCLUDE(file1 [OPTIONAL])
INCLUDE(module [OPTIONAL])
OPTIONAL参数的作用是文件不存在也不会产生错误。
你可以指定载入一个文件,如果定义的是一个模块,那么将在CMAKE_MODULE_PATH中搜索这个模块并载入。


2、INSTALL指令

INSTALL指令用于定义安装规则,安装的内容可以包括目标二进制、动态库、静态库以及文件、目录、脚本等。

INSTALL指令包含了各种安装类型,我们需要一个个分开解释:
目标文件的安装:
INSTALL(TARGETS targets...
[[ARCHIVE|LIBRARY|RUNTIME]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS
[Debug|Release|...]]
[COMPONENT <component>]
[OPTIONAL]
] [...])

参数中的TARGETS后面跟的就是我们通过ADD_EXECUTABLE或者ADD_LIBRARY定义的目标文件,可能是可执行二进制、动态库、静态库。

目标类型也就相对应的有三种,ARCHIVE特指静态库,LIBRARY特指动态库,RUNTIME特指可执行目标二进制。

DESTINATION定义了安装的路径,如果路径以/开头,那么指的是绝对路径,这时候CMAKE_INSTALL_PREFIX其实就无效了。如果你希望使用CMAKE_INSTALL_PREFIX来定义安装路径,就要写成相对路径,即不要以/开头,那么安装后的路径就是
${CMAKE_INSTALL_PREFIX}/<DESTINATION定义的路径>

举个简单的例子:
INSTALL(TARGETS myrun mylib mystaticlib
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION libstatic
)
上面的例子会将:
可执行二进制myrun安装到${CMAKE_INSTALL_PREFIX}/bin目录
动态库libmylib安装到${CMAKE_INSTALL_PREFIX}/lib目录
静态库libmystaticlib安装到${CMAKE_INSTALL_PREFIX}/libstatic目录
特别注意的是你不需要关心TARGETS具体生成的路径,只需要写上TARGETS名称就可以了。


3、FIND_指令

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

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


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


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


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


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)


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)之类的语句很容易引起歧义。

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指令,整个语句块才会得到真正的执行。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CMAKE_BUILD_TYPE是一个CMake的变量,用于配置构建类型,例如Debug、Release等。\[2\]它的默认值是一个空字符串,如果开发人员没有显式地设置它,对于单个和多个配置生成器都会导致致命错误。\[1\]为了处理这种情况,可以通过让项目提供一个默认值来处理,或者使用多组态和单组态生成器的技术来提供健壮的行为。\[1\]另外,如果我们想要将设置的编译类型应用于所有用户的各个子项目,可以直接在项目顶层的CMakeLists.txt文件中设置默认的编译类型。\[3\] #### 引用[.reference_title] - *1* [CMake(十二):构建类型](https://blog.csdn.net/jjjstephen/article/details/122496126)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [【CMake】构建类型详细解读](https://blog.csdn.net/Darlingqiang/article/details/131571974)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [从零开始 CMake 学习笔记 (F)Build Type](https://blog.csdn.net/qq_43232373/article/details/124306964)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值