CMake 入门/Out-of-source Build

维基教科书,自由的教学读本
跳到导航 跳到搜索

CMake 如何决定目录[编辑]

CMake 的参数格式如下

cmake [選項] <source tree 根目錄>
cmake [選項] <binary tree 根目錄>

在 CMake 命令列最后一项所指定的路径将被视为 source tree 根目录,当其他选项缺省时此目录为必要参数。若命令列没有给定路径 CMake 才会将目前工作资料夹当成 source tree 根目录。 source tree 根目录必须含有 CMakeLists.txt ,否则会发生错误。

另外,当命令列指定的路径下含有 CMakeCache.txt 时(通常是前次建置时遗留下的),该路径也会被当成 binary tree 根目录,否则 CMake 一律会把目前工作资料夹当成 binary tree 根目录。

取得路径资讯[编辑]

CMake 提供了几个变数让使用者在撰写 CMakeLists 时取得路径资讯,这里先介绍其中几个:

CMAKE_SOURCE_DIR
内容为 source tree 根目录的完整路径,也就是 CMake 开始建置过程的进入点。
CMAKE_BINARY_DIR
内容为 binary tree 根目录的完整路径,在 in-source build 的时候值与 CMAKE_SOURCE_DIR 相同。
PROJECT_SOURCE_DIR
目前所属专案的原始码根目录,即内含 project() 指令的 CMakeLists 所在资料夹。前面的例子没有阶层之分,所以 PROJECT_SOURCE_DIR 和 CMAKE_SOURCE_DIR 相同;更复杂的专案会包含数个子专案,子专案下面还可能会有多个资料夹,PROJECT_SOURCE_DIR 内容为目前正在处理中的专案最上层目录。
PROJECT_BINARY_DIR
目前所属专案的建置根目录,专案意义同上。在 in-source build 时和 PROJECT_SOURCE_DIR 相同。
CMAKE_CURRENT_SOURCE_DIR
目前正在处理的 CMakeLists.txt 所在位置。
CMAKE_CURRENT_BINARY_DIR
目前正在处理的 CMakeLists.txt 对应的建置资料夹位置。当然,在 in-source build 时和 CMAKE_CURRENT_SOURCE_DIR 相同。

这里要注意的是,CMake 中都使用绝对路径来表示档案位置。

为了了解 CMake 目前的 source tree 和 binary tree 为何,我们可以在 CMakeLists 当中加上:

message("CMAKE_SOURCE_DIR= ${CMAKE_SOURCE_DIR}")
message("CMAKE_BINARY_DIR= ${CMAKE_BINARY_DIR}")

在源码之外建置[编辑]

本章采用和之前相同的范例,目录树的架构如下,各原始码的内容请参考前一节--建置基本的执行档

  • ex2/
    • src/
      • CMakeLists.txt
      • calc.c
      • calc.h
      • main.c


Note
若是沿用前一个例子的档案,请先清除源码根目录所有CMake 中间档,否则源码根目录含有前次留下的 CMakeCache.txt,仍会被 CMake 优先视为建置根目录,于是执行 In-source build


设目前工作目录为 ex2/,执行下列指令:

$ mkdir -p build
$ cd build
$ cmake ../src
$ make

如果你的编译器并非系统预设,别忘了依照需求指定 Generator:

$ cmake -G "Unix Makefiles" ../src
$ cmake -G "MSYS Makefiles" ../src
> cmake -G "Visual Studio 9 2008" ../src


执行结束后,ex2/build 下会出现各项中间档、makefile 以及最终的 ex2 执行档,但 ex2/src 原封不动,只有三个 C 源码和一个 CMakeLists.txt。之后若出现什么疑难杂症,可以轻松将 ex2/build 砍掉重练。

注意事项[编辑]

在执行 Out-of-source build 之前必须先确定所指定的源码根目录是否干净,若是该目录下含有前次留下的 CMakeCache.txt 仍会执行 In-source build。

由于 CMake 生成的 makefile 当中并不会包含 make distclean 的 rule,因此强烈建议采用 out-of-source build,发布的时候只需将干净的 source tree 打包即可。