CMake:检测python解释器和python库

CMake:检测python解释器和python库

  • 导言
  • 检测python解释器
    • CMakeLists.txt
    • 输出
    • 附录
  • 检测python库
    • 项目结构
    • CMakeLists.txt
    • 相关源码
    • 附录

导言

python是一种非常流行的语言。许多项目用python编写的工具,从而将主程序和库打包在一起,或者在配置或构建过程中使用python脚本。这种情况下,确保运行时对python解释器的依赖也需要得到满足。本篇将展示如何检测和使用python解释器。

除此之外,还有其他方法可以将解释语言(如python)与编译语言(如CC++)组合在一起使用。一种是扩展python,通过编译成共享库的CC++模块在这些类型上提供新类型和新功能。另一种是将python解释器嵌入到CC++程序中。两种方法都需要下列条件:

  • python解释器的工作版本
  • python头文件python.h的可用性
  • python运行时库libpython

检测python解释器

项目地址:

https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter3/01

CMakeLists.txt

在这里插入图片描述

find_package(PythonInterp REQUIRED)

使用find_package命令找到python解释器。

find_package是用于发现和设置包的CMake模块的命令。这些模块包含CMake命令,用于标识系统标准位置中的包。CMake模块文件称为Find<name>.cmake,当调用find_package(<name>)时,模块中的命令将会运行。

除了在系统上实际查找包模块之外,查找模块还会设置了一些有用的变量,反映实际找到了什么,也可以在自己的CMakeLists.txt中使用这些变量。对于python解释器,相关模块为FindPythonInterp.cmake附带的设置了一些CMake变量:

  • PYTHONINTERP_FOUND:是否找到解释器
  • PYTHON_EXECUTABLEpython解释器到可执行文件的路径
  • PYTHON_VERSION_STRINGpython解释器的完整版本信息
  • PYTHON_VERSION_MAJORpython解释器的主要版本号
  • PYTHON_VERSION_MINORpython解释器的次要版本号
  • PYTHON_VERSION_PATCHpython解释器的补丁版本号

可以强制CMake,查找特定版本的包。例如,要求python解释器的版本大于或等于2.7find_package(PythonInterp 2.7)

CMake有很多查找软件包的模块。建议在CMake在线文档中查询Find<package>.cmake模块,并在使用它们之前详细阅读它们的文档。find_package命令的文档可以参考 :

https://cmake.org/cmake/help/v3.5/command/find_ackage.html

execute_process(COMMAND${PYTHON_EXECUTABLE} "-c" "print('Hello, world!')"RESULT_VARIABLE _statusOUTPUT_VARIABLE _hello_worldERROR_QUIETOUTPUT_STRIP_TRAILING_WHITESPACE)

执行python命令并捕获它的输出和返回值。

输出

-- Found PythonInterp: /usr/bin/python3.8 (found version "3.8.10") 
-- RESULT_VARIABLE is: 0
-- OUTPUT_VARIABLE is: Hello, python interpreter!
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jiangli/repo/tutorials/cmake-tutorial/chapter3/01/build

附录

软件包没有安装在标准位置时,CMake无法正确定位它们。用户可以使用-D参数传递相应的选项,告诉CMake查看特定的位置。python解释器可以使用以下配置:

$ cmake -D PYTHON_EXECUTABLE=/custom/location/python ..

这将指定非标准/custom/location/python安装目录中的python可执行文件。

注意:每个包都是不同的,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!"

检测python库

项目结构

.
├── CMakeLists.txt
└── hello_embedded_python.c

项目地址:

https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter3/02

CMakeLists.txt

在这里插入图片描述
为了确保可执行文件、头文件和库都有一个匹配的版本。这对于不同版本,可能在运行时导致崩溃。通过FindPythonInterp.cmake中定义的PYTHON_VERSION_MAJORPYTHON_VERSION_MINOR来实现:

find_package(PythonInterp REQUIRED)
find_package(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} EXACT REQUIRED)

可执行文件包含python.h头文件。因此,这个目标的include目录必须包含pythoninclude目录,可以通过PYTHON_INCLUDE_DIRS变量进行指定:

target_include_directories(hello_embedded_pythonPRIVATE ${PYTHON_INCLUDE_DIRS}
)

将可执行文件链接到python库,通过PYTHON_LIBRARIES变量访问:

target_link_libraries(hello_embedded_pythonPRIVATE ${PYTHON_LIBRARIES}
)

相关源码

在这里插入图片描述
此代码将在程序中初始化python解释器的实例,并使用pythonprint函数,打印字符串。

附录

python不在标准安装目录中,如何确定python头文件和库的位置是正确的?

对于python解释器,可以通过-D选项传递PYTHON_LIBRARYPYTHON_INCLUDE_DIR选项来强制CMake查找特定的目录。这些选项指定了以下内容:

  • PYTHON_LIBRARY:指向python库的路径
  • PYTHON_INCLUDE_DIRpython.h所在的路径

这样,就能获得所需的python版本。

注意:有时需要将-D PYTHON_EXECUTABLE-D PYTHON_LIBRARY-D PYTHON_INCLUDE_DIR传递给CMake CLI,以便找到及定位相应的版本的组件。

要将python解释器及其开发组件匹配为完全相同的版本可能非常困难,对于那些将它们安装在非标准位置或系统上安装了多个版本的情况尤其如此。CMake 3.12版本中增加了新的python检测模块,来解决这个问题。CMakeLists.txt的检测部分也将简化为:

find_package(Python COMPONENTS Interpreter Development REQUIRED)

最后:用积极的态度面对生活,正面面对生活中的任何人、事!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/23806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MCU的类型和应用领域简介

MCU&#xff08;Microcontroller Unit&#xff09;根据存储器类型可分为无片内ROM型和带片内ROM型。无片内ROM型的芯片需要外接EPROM才能应用&#xff0c;而带片内ROM型则有不同的子类型&#xff0c;如片内EPROM型、MASK片内掩模ROM型和片内Flash型。 MCU还可以按照用途分为通…

Cesium 实战教程 - 调整 3dtiles 倾斜摄影大小

Cesium 实战教程 - 调整 3dtiles 倾斜摄影大小 核心代码完整代码在线示例 之前由于误解遇到一个特殊的需求&#xff1a;想要把三维球上叠加倾斜摄影进行自由放大缩小&#xff0c;跟随地图的缩放进行缩放。 后来经过搜索、尝试&#xff0c;终于实现了需求。 但是&#xff0c;后…

用Abp实现找回密码和密码强制过期策略

用户找回密码&#xff0c;确切地说是重置密码&#xff0c;为了保证用户账号安全&#xff0c;原始密码将不再以明文的方式找回&#xff0c;而是通过短信或者邮件的方式发送一个随机的重置校验码&#xff08;带校验码的页面连接&#xff09;&#xff0c;用户点击该链接&#xff0…

SpringBoot 日志文件

一、日志的作用 日志是程序的重要组成部分&#xff0c;想象一下&#xff0c;如果程序报错了&#xff0c;不让你打开控制台看日志&#xff0c;那么你能找到报错的原因吗 答案是否定的&#xff0c;写程序不是买彩票&#xff0c;不能完全靠猜&#xff0c;因此日志对于我们来说&a…

C语言数组笔试题(详解)

目录 插入知识&#xff1a; 一.指向函数指针数组的指针 二.回调函数 什么是回调函数&#xff1f; 三.数组笔试题 个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生&#x1f43b;‍❄个人主页&#xff1a;GOTXX &#x1f4…

【Apollo学习笔记】—— 相机仿真

文章目录 前言相关代码整理 测试实践文件目录包管理BUILD文件以及cyberfile.xml文件源程序BUILD运行结果其他参考CameraOutput channels启动camera驱动启动camera video compression驱动 前言 本文是对Cyber RT的学习记录,文章可能存在不严谨、不完善、有缺漏的部分&#xff0…

[迁移学习]领域泛化

一、概念 相较于领域适应&#xff0c;领域泛化(Domain generalization)最显著的区别在于训练过程中不能访问测试集。 领域泛化的损失函数一般可以描述为以下形式&#xff1a; 该式分为三项&#xff1a;第一项表示各训练集权重的线性组合&#xff0c;其中π为使该项最小的系数&a…

react工程化配置

道阻且长&#xff0c;行而不辍&#xff0c;未来可期 1.安装react yarn create react-app demo --template typescript cd demo yarn start2.配置蓝图模版 2.1安装blueprint插件 https://github.com/shredor/blueprint-templates-cli#readme yarn add blueprint-templates-c…

WAF绕过-漏洞利用篇-sql注入+文件上传-过狗

WAF绕过主要集中在信息收集&#xff0c;漏洞发现&#xff0c;漏洞利用&#xff0c;权限控制四个阶段。 1、什么是WAF&#xff1f; Web Application Firewall&#xff08;web应用防火墙&#xff09;&#xff0c;一种公认的说法是“web应用防火墙通过执行一系列针对HTTP/HTTPS的安…

webpack基础知识六:说说webpack的热更新是如何做到的?原理是什么?

一、是什么 HMR全称 Hot Module Replacement&#xff0c;可以理解为模块热替换&#xff0c;指在应用程序运行过程中&#xff0c;替换、添加、删除模块&#xff0c;而无需重新刷新整个应用 例如&#xff0c;我们在应用运行过程中修改了某个模块&#xff0c;通过自动刷新会导致…

【C#学习笔记】装箱和拆箱

文章目录 装箱和拆箱性能消耗装箱拆箱 比较var&#xff0c;object&#xff0c;dynamic&#xff0c;\<T\>varobject\<T\> 泛型dynamic 装箱和拆箱 在讲引用类型object的时候&#xff0c;我们说它是万能的&#xff0c;却没说它万能在哪里。 除了object为每一种变量…

Grafana集成prometheus(4.Grafana添加预警)

上文已经完成了grafana对prometheus的集成及数据导入&#xff0c;本文主要记录grafana的预警功能&#xff08;以内存为例&#xff09; 添加预警 添加入口&#xff08;2个&#xff09; databorard面板点击edit&#xff0c;下方有个Alert的tab&#xff0c;创建Alert rules依赖…

ffmpeg + nginx 实现rtsp视频流转m3u8视频流,转码推流(linux)

FFmpeg即是一款音视频编解码工具&#xff0c;同时也是一组音视频编码开发套件&#xff0c;作为编码开发套件&#xff0c;它为开发者提供了丰富的音视频处理的调用接口。 FFmpeg提供了多种媒体格式的封装和解封装&#xff0c;包括多种音视频编码、多种协议的流媒体、多种多彩格式…

苹果电脑第三方应用程序卸载工具CleanMyMacX4.14

CleanMyMacX&#xff0c;这是一款可以帮助你快速识别并卸载电脑上的多个应用程序的第三方工具&#xff0c;省去了逐个卸载的繁琐步骤。 我们首先要到下载CleanMyMacX&#xff0c; CleanMyMac X全新版下载如下: https://wm.makeding.com/iclk/?zoneid49983 然后&#xff0c…

【项目 计网2】4.4网络模型 4.5协议 4.6网络通信的过程

文章目录 4.4网络模型OSI七层参考模型TCP/IP四层模型&#xff08;常用&#xff09;简介四层介绍 4.5协议简介常见协议UDP协议TCP协议IP协议以太网帧协议&#xff08;MAC地址封装&#xff09;ARP协议&#xff08;IP->MAC&#xff09; 4.6网络通信的过程封装分用 4.4网络模型 …

Stable Diffusion 硬核生存指南:WebUI 中的 GFPGAN

本篇文章聊聊 Stable Diffusion WebUI 中的核心组件&#xff0c;强壮的人脸图像面部画面修复模型 GFPGAN 相关的事情。 写在前面 本篇文章的主角是开源项目 TencentARC/GFPGAN&#xff0c;和上一篇文章《Stable Diffusion 硬核生存指南&#xff1a;WebUI 中的 CodeFormer》提…

k8s存储卷

目录 一、为什么要存储卷&#xff1f;二、emptyDir存储卷三、hostPath存储卷四、 nfs共享存储卷五、PVC 和 PV5.1 PV和PVC之间的相互作用遵循的生命周期5.2 PV 的状态5.3 一个PV从创建到销毁的具体流程 六、静态创建pv和pvc资源由pod运用过程6.1 在NFS主机上创建共享目录&#…

03 制作Ubuntu启动盘

1 软碟通 我是用软碟通制作启动盘。安装软碟通时一定要把虚拟光驱给勾选上&#xff0c;其余两个可以看你心情。 2 镜像文件 我使用清华镜像网站找到的Ubuntu镜像文件。 Index of /ubuntu-releases/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 请自己选择镜像…

K8S系列文章之 使用Kind部署K8S 并发布服务

简单介绍 kind 即 Kubernetes In Docker&#xff0c;顾名思义&#xff0c;就是将 k8s 所需要的所有组件&#xff0c;全部部署在一个docker容器中&#xff0c;是一套开箱即用的 k8s 环境搭建方案。使用 kind 搭建的集群无法在生产中使用&#xff0c;但是如果你只是想在本地简单…

队列中offer,add;poll,remove;peek,element之间的区别

offer和add的区别 offer() 和 add() 都是向队列中加入新项。 一些队列有大小限制&#xff0c;因此如果想在一个满的队列中加入一个新项&#xff0c;多出的项就会被拒绝。 这时新的offer方法就可以起作用了。它不是对调用add()方法抛出一个unchecked异常&#xff0c;而只是得…