runsisi's

technical notes

CMake 基础使用

2019-08-29 runsisi#cpp#cmake

CMAKE_PREFIX_PATH

CMAKE_PREFIX_PATH 用于定义额外的 bin/lib(64)/include 搜索路径(默认为空)。

如果 CMAKE_PREFIX_PATH 指定的路径中没有 /bin, /lib(64), /include 后缀,cmake 的 find_xxx 命令会为每个路径自动加上 /bin, /lib(64), /include 目录。

CMAKE_PREFIX_PATH 既可以通过环境变量导出:

$ export CMAKE_PREFIX_PATH=/home/runsisi:/usr/local:/opt/runsisi/python3/bin

同时它也是一个 CMake 内置的变量,因此还可以在命令行上通过 -D 选项或者在 CMakeList.txt 中通过 set 或者 list 命令显式定义。

$ cmake .. -DPythonInterp_FIND_VERSION=3.6 -DPythonInterp_FIND_VERSION_MAJOR=3 -DCMAKE_PREFIX_PATH=/home/runsisi\;/usr/local\;/opt/runsisi/python3/bin
$ cmake .. -DPythonInterp_FIND_VERSION=3.6 -DPythonInterp_FIND_VERSION_MAJOR=3 -DCMAKE_PREFIX_PATH='/home/runsisi;/usr/local;/opt/runsisi/python3/bin'
$ cmake .. -DPythonInterp_FIND_VERSION=3.6 -DPythonInterp_FIND_VERSION_MAJOR=3 -DCMAKE_PREFIX_PATH="/home/runsisi;/usr/local;/opt/runsisi/python3/bin"
set(CMAKE_PREFIX_PATH "/home/runsisi;/usr/local;/opt/runsisi/python3/bin")

或:

list(APPEND CMAKE_PREFIX_PATH "/home/runsisi;/usr/local;/opt/runsisi/python3/bin")

注意冒号、分号、带转义的分号三种方式分隔符的使用(带转义是 shell 的限制而已),CMake 通过分号定义列表,空白分隔参数。

CMAKE_MODULE_PATH

CMAKE_PREFIX_PATH 不同,CMAKE_MODULE_PATH 不支持通过环境变量导出(默认为空),因此必须在命令行上通过 -D 选项或者在 CMakeList.txt 中通过 set 或者 list 命令显式定义:

$ cmake .. -DPythonInterp_FIND_VERSION=3.6 -DPythonInterp_FIND_VERSION_MAJOR=3 -DCMAKE_PREFIX_PATH="/home/runsisi;/usr/local;/opt/runsisi/python3/bin" -DCMAKE_MODULE_PATH=~/working/test/pyleak/cmake/modules

或:

set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")

或:

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")

增加多个路径的方式与 CMAKE_PREFIX_PATH 类似,通过分号进行分隔。

调试打印

message 调试打印,如:

message("_Python_NAMES: " "${_Python_NAMES}")
message("_Python_NAMES: ${_Python_NAMES}")
message("PYTHON_EXECUTABLE: " "${PYTHON_EXECUTABLE}")
message("PYTHON_EXECUTABLE: ${PYTHON_EXECUTABLE}")

find-package 模式

调试 FindXxx 模块时可以使用 find-package 模式,这样就不用每次都删除 cmake 生成的中间文件:

$ cmake .. -DPythonInterp_FIND_VERSION=3.6 -DPythonInterp_FIND_VERSION_MAJOR=3 -DCMAKE_PREFIX_PATH="/home/runsisi;/usr/local;/opt/runsisi/python3/bin" -DNAME=PythonInterp -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=EXIST --find-package

不过需要注意的是,find-package 模式与项目无关,如果需要测试用户自定义的 FindXxx 模块,有两种方法:

  1. 拷贝至 CMake 自带的模块目录中,如:
/usr/share/cmake-3.10/Modules/
/usr/share/cmake/Modules/
  1. 在命令行上显式定义 CMAKE_MODULE_PATH
$ cmake -DCMAKE_MODULE_PATH=~/working/test/pyleak/pybind11/tools -DNAME=PythonLibsNew -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=EXIST --find-package

如果开启 --trace 等调试选项,需要在把这些选项放在 --find-package 之前。

注意:CMake 自带的 FindXxx 模块具有最低优先级

运行

最后,可以以 verbose 模式运行 make 以检验 CMake 生成的 Makefile 结果:

$ make VERBOSE=1

参考资料

Learn CMake’s Scripting Language in 15 Minutes

https://preshing.com/20170522/learn-cmakes-scripting-language-in-15-minutes/

Some CMake tips

https://samthursfield.wordpress.com/2015/10/20/some-cmake-tips/

CMake: dependencies between targets and files and custom commands

https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom-commands/

CMake stuff i wish i knew earlier

http://www.brianlheim.com/2018/04/09/cmake-cheat-sheet.html

Displaying CMake variables

https://stackoverflow.com/questions/31343813/displaying-cmake-variables

overriding CMAKEMODULEPATH

https://mail.kde.org/pipermail/kde-buildsystem/2010-August/007285.html

How to get CMake find what you want it to

https://blogs.kde.org/2008/12/12/how-get-cmake-find-what-you-want-it

CMake Useful Variables

https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Useful-Variables

It’s Time To Do CMake Right

https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/

An Introduction to Modern CMake

https://cliutils.gitlab.io/modern-cmake/

Does settargetproperties in CMake override CMAKECXXFLAGS?

https://stackoverflow.com/questions/5096881/does-set-target-properties-in-cmake-override-cmake-cxx-flags

What is the modern method for setting general compile flags in CMake?

https://stackoverflow.com/questions/23995019/what-is-the-modern-method-for-setting-general-compile-flags-in-cmake

Does cmake have something like targetlinkoptions?

https://stackoverflow.com/questions/25043458/does-cmake-have-something-like-target-link-options