CMake用法

527 阅读3分钟

CMake

cmake官方手册CMake Reference Documentation — CMake 3.15.7 Documentation

CmakeLists.txt文件语法

所有命令均可以在官网找到cmake-commands(7) — CMake 3.15.7 Documentation

1. 指定 cmake 的最小版本

cmake_minimum_required(VERSION 3.10)

2. 设置项目名称

project(NS3 CXX C)

3. option() (跳过)

option(<variable> "help_text"  [value])

为使用者提供一个选项可选为ON或者OFF,默认valueOFF

option(NS3_ASSERT "Enable assert on failure" OFF)
option(NS3_DES_METRICS "Enable DES Metrics event collection" OFF)
option(NS3_EXAMPLES "Enable examples to be built" OFF)
option(NS3_LOG "Enable logging to be built" OFF)
option(NS3_TESTS "Enable tests to be built" OFF)

4. set()设置变量

设置普通变量

命令格式set(<variable> <value>... [PARENT_SCOPE]) # 设置普通变量

命令含义:将缓存条目variable设置为值<value>...

可以设置EXECUTABLE_OUTPUT_PATH的值来确定可执行文件的输出路径

设置缓存条目

命令格式set(<variable> <value>... CACHE <type> <docstring> [FORCE])

命令含义:将缓存条目variable设置为值<value>...,除非用户进行设置或使用了选项FORCE,默认情况下缓存条目的值不会被覆盖。缓存条目可以通过CMAKE的GUI界面的add entry按钮来增加。缓存条目的实质为可以跨层级进行传递的变量,类似于全局变量

缓存条目的<type>主要有以下几类:

  • BOOL:布尔值ON/OFF,CMAKE的GUI界面对此类缓存条目会提供一个复选框。
  • FILEPATH:文件路径,CMAKE的GUI界面对此类缓存条目会提供一个文件选择框。
  • PATH:目录路径,CMAKE的GUI界面对此类缓存条目会提供一个目录选择框。
  • STRING / STRINGS:文本行,CMAKE的GUI界面对此类缓存条目会提供一个文本框(对应STRING)或下拉选择框(对应STRINGS)。
  • INTERNAL:文本行,但是只用于内部,不对外呈现。主要用于运行过程中存储变量,因此使用该type意味着使用FORCE
    缓存条目的几个注意事项:
    1)如果变量先前未定义或者使用了FORCE选项,则缓存条目会直接被赋值。
    2)可以在使用cmake构建的使用通过-D选项来给缓存条目赋值,这样CMakeLists.txt内的set命令只会为缓存条目添加类型。
    3)如果变量类型是目录或者文件路径,通过-D选项传入的若只是相对路径,那么set会给这个相对路径前添加当前的工作目录以变成绝对路径(如果已经是绝对路径则不会处理)。

docstring应该是一个解释的作用,在GUI界面可以看到这个hint

设置环境变量

命令格式set(ENV{<variable>} [<value>])

命令含义:将环境变量设置为值<value>(注意没有...),接着使用$ENV{<variable>}会得到新的值。cmake中的环境变量可以参考:环境变量

环境变量设置的几个注意事项:
1)该命令设置的环境变量只在当前的cmake进程生效,既不会影响调用者的环境变量,也不会影响系统环境变量。
2)如果<value>值为空或者ENV{<variable>}后没有参数,则该命令会清除掉当前环境变量的值。
3)<value>后的参数会被忽略。

5. 添加子目录并构建

add_subdirectory(子目录路径)添加一个子目录并构建该子目录,子目录下应该包含CMakeLists.txt文件和代码文件。

  • 命令形式:add_subdirectory(子目录路径 子目录编译文件的输出路径)
# Build NS3 library core
add_subdirectory(src)

# Build NS library examples
add_subdirectory(examples)

# Build scratch/simulation scripts
add_subdirectory(scratch)

# Build test utils
add_subdirectory(utils)

6. 设置编译类型

add_executable(可执行文件名不需要exe后缀 源文件名) # 生成可执行文件
add_library(生成库文件名 SHARED/STATIC 源文件) # 生成库文件
target_link_library(可执行文件名 链接的多个共享库) # 将可执行文件连接到共享库

7. include指令

include指令一般用于语句的复用,如果有一些语句需要在很多CMakeLists.txt文件中使用,为避免重复编写,可以将其写在.cmake文件中,然后在需要的CMakeLists.txt文件中进行include操作就行了 一般在要include.cmake文件中会定义macro宏和函数function,定义方式为:

# 宏定义
macro(<name> [args...])
    ... 
    # 命令语句
    ...
endmacro()

# 函数定义
function(<name> [args...])
    ... 
    # 命令语句
    ...
endfunction()

对于宏和函数的参数而言:

  • 当宏和函数调用的时候,如果传递的是经set设置的变量,必须通过${}取出内容;
  • 在宏的定义过程中,对变量进行的操作必须通过${}取出内容,而函数就没有这个必要。

8. 添加搜索路径

include_directories(路径) # 添加所有的头文件搜索路径
target_include_directories(目标(可执行文件/库) 路径)
link_directorues(路径) # 添加多个特定的库文件搜索路径

cmake命令行

开始构建文件

项目主目录存在一个CMakeLists.txt文件

两种方式设置编译规则:

  1. 包含源文件的子文件夹包含CMakeLists.txt文件,主目录的CMakeLists通过add_subdirectory()添加子目录即可。
  2. 包含源文件的子文件夹不包含CMakeLists.txt文件,子目录编译规则体现在主目录的CMakeLists.txt文件中。

编译流程

  1. 手动编写CMakeLists.txt文件
  2. 执行cmake PATH命令生成Makefile(PATH是顶层CMakeLists.txt文件所在的目录),但是生成的makefile文件会放在当前目录中
  3. 执行命令make进行编译
常用且推荐的编译方式:外部构建

将编译输出文件与源文件放到不同目录中。

构建的工程目录中要有CMakeLists.txtbuild目录,先cd进入build文件夹,然后输入命令:

cmake .. # 编译上级目录的CMakeLists.txt生成makefile和其他文件
make     # 执行make命令,生成target

关于cmake构建的参数

cmake可以带上一些选项和参数,常用:

  • -D为缓存条目和option赋值
  • -S指定源文件路径
  • -B指定构建的路径