Cmake使用笔记

Graphviz: 查看dependenices

预定于变量

变量名 描述 备注
PROJECT_SOURCE_DIR 工程的根目录
PROJECT_BINARY_DIR 运行 cmake 命令的目录,通常是 ${PROJECT_SOURCE_DIR}/build
PROJECT_NAME 返回通过 project 命令定义的项目名称
CMAKE_CURRENT_SOURCE_DIR 当前处理的 CMakeLists.txt 所在的路径
CMAKE_CURRENT_BINARY_DIR target/out 编译目录,即build目录
CMAKE_CURRENT_LIST_DIR CMakeLists.txt 的完整路径
CMAKE_CURRENT_LIST_LINE 当前所在的行
CMAKE_MODULE_PATH 定义自己的 cmake 模块所在的路径,SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
EXECUTABLE_OUTPUT_PATH 重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH 重新定义目标链接库文件的存放位置

指定cmake的最小版本

1
cmake_minimum_required(VERSION3.4.1)
  • 这行命令是可选的,我们可以不写这句话,但在有些情况下,如果 CMakeLists.txt 文件中使用了一些高版本 cmake 特有的一些命令的时候,就需要加上这样一行,提醒用户升级到该版本之后再执行 cmake。

设置项目名称

1
project(demo)
  • 这个命令不是强制性的,但最好都加上。它会引入两个变量 demo_BINARY_DIRdemo_SOURCE_DIR
  • 同时,cmake 自动定义了两个等价的变量 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR

设置编译类型

1
2
3
add_executable(demo demo.cpp)       # 生成可执行文件
add_library(common STATIC util.cpp) # 生成静态库
add_library(common SHARED util.cpp) # 生成动态库或共享库
  • add_library 默认生成是静态库,通过以上命令生成文件名字,
  • 在 Linux 下是:demo、libcommon.a、libcommon.so
  • 在 Windows 下是:demo.exe、common.lib、common.dll

构建命令

1
cmake -B <build tree> -S <source tree>
1
cmake --build <build tree>
1
cmake -G <generator-name> <path-to-source>
1
cmake --system-information [file]
  • 将信息信息输出到文件中(变量、命令、宏和其它设置)
避免重复include .h文件
1
#pragma once

打印include header file

target_compile_options(debug PRIVATE -H)

6、Linking with cmake

  • static
  • share
  • share module

ODR-One Definition Rule

  • 处理代码命名冲突

image.png

ELF
  • 标识目标操作系统
  • elf文件类型
  • 目标指令集体系结构
  • program headers table 和 section headers table 信息
.text
  • 机器代码,包含处理器需要执行的所有指令。
.data
  • 定义了初始化值的全局/静态变量
.bss
  • 未定义初始化值的全局/静态变量,程序加载的时候使用0值初始化
.rodata
  • 所有只读常量值
.strtab
  • 包含所有的string常量
.shstrtab
  • 包含所有段(section)的名字
section headers table
  • 包含了名称、类型、标志、内存中目标地址、文件中的偏移量以及其它信息。
  • 通过该信息可了解文件的组成成分。–目录的角色

Dependencies Manager

  • 从 CMAKE_MODULE_PATH 变量定义的路径开始检索dependencies。检索优先级find-modules > config-files > cmake已安装的内置模块
  • CMAKE_MODULE_PATH 默认为空

find_package (具备PKGNAMEConfig.cmake/pkgname-config.cmake的模块可用)

  • find_package( [version] [EXACT] [QUIET] [REQUIRED])
  • 使用find_package 方法检索到目标依赖后,通常可以通过下列变量来使用检索到的依赖库
    • <PACKAGE_NAME>_FOUND
    • <PACKAGE_NAME>_INCLUDE_DIRS or <PACKAGE_NAME>_INCLUDES
    • <PACKAGE_NAME>_LIBRARIES or <PACKAGE_NAME>_LIBS
    • <PACKAGE_NAME>_DEFINATIONS
    • IMPORTED

FindPkgConfig (具备PkgConfig的模块可用)

.pc文件示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
prefix=/usr/local
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib

Name: foobar
Description: A foobar library
Version: 1.0.0
Cflags: -I${includedir}/foobar
Libs: -L${libdir} -lfoobar
  • 获取链接库标识:pkg-config –libs pkg name
  • 获取库的include 目录:pkg-config –cflags pkg name

PKG_CONFIG_EXECUTABLE

1、使用PKG_CONFIG_FOUND确认库是否可用 2、使用pkg_check_modules 扫描包

custom find-module

find-module可提供如下变量

  • <PKG_NAME>_FIND_REQUIRED:find_package(<PKG_NAME> REQUIRED) 被调用时,如果找到目标库,变量值设置为1,否则调用message(FATAL_ERROR)
  • <PKG_NAME>_FIND_QUIETLY:find_package(<PKG_NAME> QUIET)被调用时,如果找到目标库,变量值设置为1,否则
  • <PKG_NAME>_FIND_VERSION :

构建自定义find-module步骤

  • 引入CMakeFindDependencyMacro宏,使用find_dependency()检索目标库
  • 使用find_library查找目标库的library路径
  • 使用find_path 查找目标库headers路径
  • 引入FindPackageHandleStandardArgs宏。使用find_package_handle_standard_args()方法检测library和headers是否成功检索到
  • 若成功找到则执行下列步骤
  • 确定library、headers的路径
  • 创建一个 IMPORTED target
  • 设置必要的属性 IMPORTED_LOCATION、INTERFACE_INCLUDE_DIRECTORIES、IMPORTED
  • 存储库的路径到缓存变量中以避免二次查找目标库
  • 创建PQXX_FOUND缓存变量并给一个明确的值
  • 把变量标记为advanced(mark_as_advanced),除非advanced 标识被开起,否在在CMAKE GUI程序中不可见

find_dependency

Git repo

ExternalProject\FetchContent

ExternalProject_Add()

功能

  • 管理external project 的目录结构
  • 从url中下载源码
  • 支持常用的代码版本管理仓库
  • 有需要时获取更新
  • 使用cmake 或者指定的工具配置和构建project
  • 执行安装和测试操作
  • 日志文件
  • 从终端请求用户输入
  • 依赖其它的target
  • 针对构建增加自定义命令和步骤 针对使用ExternalProject_Add方法处理的external project,cmake自动执行下列操作:
  • mkdir- 针对external project创建一个目录
  • download- 从仓库或者url获取工程文件
  • update- 重新运行时刷新文件
  • patch – 可选择执行补丁命令,根据项目的需要更改下载的文件
  • configure- 针对cmake工程,执行configure操作,针对非cmake工程,需手动配置
  • build- 针对cmake工程,执行build操作,针对其它依赖,执行cmake命令
  • install- 安装cmake工程,针对其它依赖执行cmake install 命令
  • test- 如果定义来测试选项,执行测试操作