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
- src/
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 打包即可。