深入理解CMake(1): CMake命令行参数

初衷

CMake能用来编写跨平台(cross-platform)的构建规则,通过这些规则来调用各个平台的编译器、链接器,生成各个目标(静态库,静态库,或者可执行)。

我第一个接触的大型C++项目是OpenCV,它是基于CMake构建的。后来接触的另一个大型C++项目是Caffe,既提供Makefile也提供CMakeLists.txt。在使用CMake的过程中对CMake的常用语法越发熟悉,甚至日常工作中的项目代码也被我用CMake进行构建。但是仍然觉得对CMake不够了解,CMake的不少用法在官方文档中的描述也感觉有些晦涩、不清晰。

好在CMake是开源项目,觉得CMake文档写的烂那就直接翻源码。而由于越来越多的C/C++开源项目使用CMake进行构建,学习和深入理解CMake对于一个C/C++(尤其是跨平台)程序员来说还是有相当的好处和必要的。(当然你也可以用gradle/bazel/buck/please/scons/xmake/emake等来构建)

此外,我也仔细看过CMake官方文档的部分章节,写过几篇蹩脚的CMake笔记文档,了解到通常越新版本的CMake特性越多。这系列blog分析的CMake源码是CMake-3.14.3版。(不得不吐槽一下:CMake官网打开速度太慢,国内各大开源镜像站点也都不收录CMake源码,CMake官方文档打开也超慢,而且写的也不够系统,中文博客讲CMake的也往往很初级)。如果你是第一次接触CMake,我觉得你最好先用用CMake,稍微熟悉一点基本用法和一些概念后再来看本篇不迟。

CMake入口:命令行参数

CMake是什么?或许我们应该从"cmake.exe是什么?"(windows),或file `which cmake`(Linux或Mac)来分析。当我们安装好CMake,它提供了一个可执行文件cmake或cmake.exe,有时候还提供一个GUI版本,比如ccmake或cmake-gui,不过GUI版本可以认为是外科,里子还是cmake命令。

那么cmake命令是什么?其实就是一个C/C++项目编译出来的可执行文件。它或许提供了一大堆支持的函数、类,但是对外的接口可以说只有一个,那就是main()函数。当我敲下cmake ..或者cmake .. -DCMAKE_BUILD_TYPE=Debug,再或者cmake --build .,cmake到底会怎么执行,其实就是看它的commandline argument parser是怎么处理的了:它能接受的(合法的)命令行参数有哪些?每一种分别是什么含义?

深入理解CMake(1): CMake命令行参数_第1张图片
image.png

$CMAKE_ROOT/Source/cmakemain.cxx可以看出,它肯定支持的三个参数是:

  • --build
  • --open
  • -E
    继续看,发现do_cmake()函数中处理了其他参数的情况,而且数量非常多:
    深入理解CMake(1): CMake命令行参数_第2张图片
    image.png

而我们看看官方文档对cmake命令行支持的参数是怎么写的,先看cmake3.13版本的文档,可以说是稀巴烂:


深入理解CMake(1): CMake命令行参数_第3张图片
image.png

再看cmake3.14版本的命令行参数文档:

深入理解CMake(1): CMake命令行参数_第4张图片
image.png

看起来有所改善,把支持的命令行参数分成了几个类别,思路上清晰了不少;不过仍然需要改进,比如说 cmake -N这一条没有被列出,但是其实后文又有提到。

根据3.14版的文档可以看出,执行cmake命令,支持7大类参数:

  • 指定CMakeLists.txt所在路径,用来生成目标平台的构建文件如Makefile、.sln、.xcodeproject等(cmake的主要特色)
  • 执行构建,相当于用通用的写法,对生成的目标平台构建描述文件进行调用,替代具体的"make"、"nmake"等写法。(个人经常用,还可以指定--target TargetName--config BUILD_TYPE
  • 用VS、XCode等打开工程(我没用过,我也觉得没必要)
  • 执行cmake脚本
  • 执行命令行工具
  • 执行find-package工具(其实很废柴,和CMakeLists.txt中的find_package()根本不是一会事儿,试了好几个包都找不到)
  • 在命令行里查看帮助(已经是9012年了,多少年前就有git help xxx --web在网页中看帮助文档了,cmake什么时候支持一下?)

你可能感兴趣的:(深入理解CMake(1): CMake命令行参数)