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指令,整个语句块才会得到真正的执行。
07-27
### CMake 使用教程、安装配置及常见问题解决方案 #### 安装 CMake 在不同的操作系统中,CMake 的安装方式有所不同。以下是一些常见的安装方法: ##### Linux 系统(以 Ubuntu 为例) 1. **离线安装** 可以从 [CMake 官网](https://cmake.org/download/) 下载适用于 Linux 的压缩包(如 `cmake-x.x.x-linux-x86_64.tar.gz`),然后进行手动安装: ```bash tar -xzvf cmake-x.x.x-linux-x86_64.tar.gz ``` 2. **配置环境变量** 将 CMake 的 `bin` 目录添加到系统环境变量中,以便全局使用: ```bash export PATH=/path/to/cmake/bin:$PATH ``` 可以将上述命令添加到 `~/.bashrc` 或 `~/.zshrc` 文件中,以便每次启动终端时自动加载: ```bash echo 'export PATH=/path/to/cmake/bin:$PATH' >> ~/.bashrc source ~/.bashrc ``` 3. **验证安装** 使用以下命令确认 CMake 是否安装成功: ```bash cmake --version ``` 如果输出 CMake 的版本号,则表示安装成功[^1]。 ##### Windows 系统 1. 从 [CMake 官网](https://cmake.org/download/) 下载 Windows 安装包(`.msi` 文件)。 2. 运行安装程序,并选择将 CMake 添加到系统环境变量中。 3. 打开命令提示符(CMD)或 PowerShell,输入以下命令验证安装: ```bash cmake --version ``` ##### macOS 系统 可以使用 Homebrew 安装 CMake: ```bash brew install cmake ``` 验证安装: ```bash cmake --version ``` #### 配置 CMake 项目 CMake 项目的核心是 `CMakeLists.txt` 文件,它定义了项目的构建规则。以下是一个简单的 CMake 项目配置示例: ```cmake # 指定 CMake 最低版本 cmake_minimum_required(VERSION 3.10) # 定义项目名称 project(HelloCMake) # 添加可执行文件目标 add_executable(hello main.cpp) ``` 1. **创建构建目录** 通常建议在项目根目录下创建一个 `build` 子目录用于存放构建生成的文件: ```bash mkdir build cd build ``` 2. **生成构建文件** 在构建目录中运行 CMake,生成 Makefile 或其他构建系统所需的文件: ```bash cmake .. ``` 3. **编译项目** 使用 `make` 命令进行编译(适用于 Linux/macOS): ```bash make ``` 或者使用 Visual Studio 打开 `.sln` 文件进行编译(适用于 Windows)。 #### 常见问题及解决方法 1. **CMake 找不到编译器** - **问题描述**:CMake 在配置过程中提示找不到编译器。 - **解决方法**:确保系统中已安装编译器(如 GCC、Clang 或 MSVC),并且编译器的路径已添加到系统环境变量中。 2. **CMakeLists.txt 文件语法错误** - **问题描述**:CMake 配置失败,提示语法错误。 - **解决方法**:检查 `CMakeLists.txt` 文件中的语法是否正确,特别是命令的大小写和参数顺序。 3. **找不到依赖库** - **问题描述**:编译过程中提示找不到某些依赖库。 - **解决方法**:确保所有依赖库已正确安装,并且在 `CMakeLists.txt` 中使用 `find_package()` 或 `include_directories()` 正确引用。 4. **Android Studio 中使用 CMake** - **问题描述**:在 Android Studio 中配置 CMake 时遇到问题。 - **解决方法**:可以使用 Android Studio 自带的 CMake 支持,创建一个支持 C++ 的项目,查看生成的 `CMakeLists.txt` 文件,确保路径和依赖项配置正确[^5]。 #### 学习资源 - **《CMake + Practice》**:这是一篇适合初学者的中文入门教程,适合了解 CMake 的基本概念和使用方法[^2]。 - **官方文档**:[CMake 官方文档](https://cmake.org/cmake/help/latest/) 是深入了解 CMake 各种命令和高级用法的最佳资源。 - **实践项目**:通过实际项目学习 CMake 的使用,尤其是复杂的项目结构和依赖管理。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值