FANGYEFENG

Aug 04, 2024

看完CMake官方教程后

CMake 官方的 tutorial 总共有十三步,每一步都会教一些关于 CMake 的一些操作和功能。
CMake 的命令字符串容许大小写混写,大写,小写,都可以,官方推荐的是全小写

第一步

1

构建一个基本的 CMake 项目
首先必须给出
cmake_minimum_required()
这个命令指示了运行该 cmake 文件的 cmake 程序必须最低为 XXX 版本,如果早于这个版本,运行终止
接着需要使用
project()
指示项目的名字,另外还可以指定大版本小版本这些,这些会影响到诸如 PROJECT_VERSION_MAJOR这样的变量
最后是使用
add_executable()
此命令的作用是在上面的项目中使用给定的源文件生成一个可执行文件

2

指定 C++标准
C++有 98、11、14、17、20、23 这些标准,这些标准也是编译器所需要的
CMake 有两个特殊变量 CMAKE_CXX_STANDARD CMAKE_CXX_STANDARD_REQUIRED 来指示这些标准
设置变量的方式是通过
set()
来设置
CMake 自己使用的全是大写的,像 CMAKE_CURRENT_BINARY_DIR 这些,且 CMAKE 前缀

3

可以让 CMakeLists 中的变量用在我们的代码中,官方说的好处是单一事实?
比如*project(Software VERSION 2.3)*命令运行完后会设置两个变量
_Software_VERSION_MAJOR_ = 2
_Software_VERSION_MINOR_ = 3
创建 以 .h.in 结尾的文件,这个文件有特殊的语法 @Var@
configure_file命令的作用是填充.h.in 文件中的@Var@并输出为.h 文件
也就是说 @Software_VERSION_MAJOR@ 会变成 @2@

第二步

1

使用
add_library()
将给定的源文件编译为库文件
当考虑到编译库时,一般来说将库的源文件放在单一的目录中。
在这个单一目录中,也需要单独的 CMakeLists 来运行它的任务–编译库
add_subdirectory
该命令会运行给定文件夹下的 CMakeLists 文件
当你要引用到某个库时,肯定是需要头文件的,这个头文件大部分情况下都不在与引用文件相同目录下,所以需要
target_include_directories
添加头文件的搜索路径
链接库与执行文件的命令
target_link_libraries()
该步也介绍了变量 PROJECT_SOURCE_DIR 依旧是全大写 : project()命令调用的所在目录

2

使用
option()创建一个布尔变量?
option(USE_DOG "<help_text>" ON)
cmake 用 ON OFF 来代表对应的 1 0
if()语句就可以用上述的变量来有条件的执行某项命令了
target_compile_definitions()命令添加预处理宏标志,类似于手动编译时加的选项 -DXXXX
gcc aaa.c -o aaa -DXXXXX 类似在代码中 #define XXXXX

第三步

1

cmake 有target这样一个概念,它可以说是要生成的库或可执行文件,它有着 宏定义、编译选项、头文件搜索路径等属性
使用target_include_directories()可以改变 target 的头文件搜索路径的属性
每一个属性都有 PUBLIC INTERFACE PRIVATE 三种类别
PUBLIC 该属性会被该 target 所用且会传递到下一个 target(即依赖该 target 的 target)
INTERFACE 该属性不会被该 target 所用、会传递到下一个 target
PRIVATE 改属性只被自己使用
当使用
target_link_libraries()时,不当是将库链到可执行文件,而且将该库(target)的属性也一并收纳进来,比如头文件搜索路径,这样的好处是只需调用该命令即可,不需要去担心有没有哪些属性没有设置好

2

target 可以只有属性没有源文件,这种 target 的作用是将属性分给其他 target 使用
使用 add_library(NAME INTERFACE) 创建名为NAME的接口库,接口库可以通过如target_xxxx_xxxx命令设置属性
然后它可以被 target_link_libraries 作为参数使用,这样它的属性便会传达到真正的库 target 去。

第四步

这一步主要讲的是生成器表达式。
生成器表达式的值是在构建系统生成期间的出来的,也就是依赖于当前的构建配置。语法是*$<>*
条件表达式:根据条件布尔值返回字符串
$condition:true_string
特殊的表达式:如判断编译的语言是否是 C++
$<COMPILE_LANGUAGE:CXX>
该式会返回 0 如果编译的语言不是 C++ 反正是 C++
判断编译器种类
$<LANG_COMPILER_ID:compiler_ids>

CMAKE_CURRENT_SOURCE_DIR 这种的值不也是在构建时期才出来的吗,也是特定于构建系统,为什么却不用*$<>去引用呢。
CMAKE_CURRENT_SOURCE_DIR 是在命令 cmake 下生成的,是生成构建配置文件时期.
用到
$<>语法的应是在cmake –build*下才确定的值,如上述的语言和编译器判断

第五步

这一步是关于 install 和 testing 的

第六步

这一步是说可以将 ctest 的结果上传到远程主机上

第七步

这一步介绍了一个很有趣的命令
check_cxx_source_compiles(<code> <resultVar>)
为可编译成可执行文件的一段代码,里面必须有main()
cmake 构建时会执行这个命令,如果*中的代码在该平台可以运行,则为*true,否则为 false

第九步

讲的是用 cpack 打包?打包成一个压缩包,格式可选,会将依赖的系统文件一起打包进来

第十步

option(BUILD_SHARED_LIBS "<helper_text>" ON/OFF)
使用该命令可选定默认的*add_library()*的行为:生成动态库

OLDER > < NEWER