3.1 检测Python解释器
NOTE:此示例代码可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-03/recipe-01 中找到。该示例在CMake 3.5版(或更高版本)中是有效的,并且已经在GNU/Linux、macOS和Windows上进行过测试。
Python是一种非常流行的语言。许多项目用Python编写的工具,从而将主程序和库打包在一起,或者在配置或构建过程中使用Python脚本。这种情况下,确保运行时对Python解释器的依赖也需要得到满足。本示例将展示如何检测和使用Python解释器。
我们将介绍find_package
命令,这个命令将贯穿本章。
具体实施
我们将逐步建立CMakeLists.txt
文件:
首先,定义CMake最低版本和项目名称。注意,这里不需要任何语言支持:
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(recipe-01 LANGUAGES NONE)
然后,使用
find_package
命令找到Python解释器:find_package(PythonInterp REQUIRED)
然后,执行Python命令并捕获它的输出和返回值:
execute_process(
COMMAND
${PYTHON_EXECUTABLE} "-c" "print('Hello, world!')"
RESULT_VARIABLE _status
OUTPUT_VARIABLE _hello_world
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
最后,打印Python命令的返回值和输出:
message(STATUS "RESULT_VARIABLE is: ${_status}")
message(STATUS "OUTPUT_VARIABLE is: ${_hello_world}")
配置项目:
$ mkdir -p build
$ cd build
$ cmake ..
-- Found PythonInterp: /usr/bin/python (found version "3.6.5")
-- RESULT_VARIABLE is: 0
-- OUTPUT_VARIABLE is: Hello, world!
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/cmake-cookbook/chapter-03/recipe-01/example/build
工作原理
find_package
是用于发现和设置包的CMake模块的命令。这些模块包含CMake命令,用于标识系统标准位置中的包。CMake模块文件称为Find<name>.cmake
,当调用find_package(<name>)
时,模块中的命令将会运行。
除了在系统上实际查找包模块之外,查找模块还会设置了一些有用的变量,反映实际找到了什么,也可以在自己的CMakeLists.txt
中使用这些变量。对于Python解释器,相关模块为FindPythonInterp.cmake
附带的设置了一些CMake变量:
- PYTHONINTERP_FOUND:是否找到解释器
- PYTHON_EXECUTABLE:Python解释器到可执行文件的路径
- PYTHON_VERSION_STRING:Python解释器的完整版本信息
- PYTHON_VERSION_MAJOR:Python解释器的主要版本号
- PYTHON_VERSION_MINOR :Python解释器的次要版本号
- PYTHON_VERSION_PATCH:Python解释器的补丁版本号
可以强制CMake,查找特定版本的包。例如,要求Python解释器的版本大于或等于2.7:find_package(PythonInterp 2.7)
可以强制满足依赖关系:
find_package(PythonInterp REQUIRED)
如果在查找位置中没有找到适合Python解释器的可执行文件,CMake将中止配置。
TIPS:CMake有很多查找软件包的模块。我们建议在CMake在线文档中查询Find<package>.cmake
模块,并在使用它们之前详细阅读它们的文档。find_package
命令的文档可以参考 https://cmake.org/cmake/help/v3.5/command/find_ackage.html 。在线文档的一个很好的替代方法是浏览 https://github.com/Kitware/CMake/tree/master/Modules 中的CMake模块源代码——它们记录了模块使用的变量,以及模块可以在CMakeLists.txt
中使用的变量。
更多信息
软件包没有安装在标准位置时,CMake无法正确定位它们。用户可以使用CLI的-D
参数传递相应的选项,告诉CMake查看特定的位置。Python解释器可以使用以下配置:
$ cmake -D PYTHON_EXECUTABLE=/custom/location/python ..
这将指定非标准/custom/location/pytho
安装目录中的Python可执行文件。
NOTE:每个包都是不同的,Find<package>.cmake
模块试图提供统一的检测接口。当CMake无法找到模块包时,我们建议您阅读相应检测模块的文档,以了解如何正确地使用CMake模块。可以在终端中直接浏览文档,本例中可使用cmake --help-module FindPythonInterp
查看。
除了检测包之外,我们还想提到一个便于打印变量的helper模块。本示例中,我们使用了以下方法:
message(STATUS "RESULT_VARIABLE is: ${_status}")
message(STATUS "OUTPUT_VARIABLE is: ${_hello_world}")
使用以下工具进行调试:
include(CMakePrintHelpers)
cmake_print_variables(_status _hello_world)
将产生以下输出:
-- _status="0" ; _hello_world="Hello, world!"
有关打印属性和变量的更多信息,请参考 https://cmake.org/cmake/help/v3.5/module/CMakePrintHelpers.html 。