conan 入门(三十四):conan 2.x实现对只有Makefile的项目(erpcgen)的封装示例

一些已有的较老旧的项目只有Makefile,一般在Linux下编译,windows下编译需要借助cygwin或msys2,对于这样的项目如何实现conanfile.py使用conan进行构建呢?本文以erpc/erpcgen为例,说明实现步骤。

eRPC (Embedded RPC是一个适用于嵌入式系统的开源RPC框架,erpc/erpcgen为其下的IDL编译器,编译基于Makefile.现在需要把它封装为conan的package.这就是我最近遇到的问题。
下面我们分步说明实现的要点

requires

erpcgen依赖很简单,只有boost

requires = "boost/[>=1.69.0]"

build_requirements

erpcgen编译依赖的工具需要flex,bision,在windows下就是winflexbison,
在windows下需要在msys2环境编译,工具依赖还要加上msys2

    def build_requirements(self):if self._settings_build.os == "Windows":self.tool_requires("winflexbison/2.5.24")self.win_bash = Trueif not self.conf.get("tools.microsoft.bash:path", check_type=str):# Windows下需要在MSYS2环境编译self.tool_requires("msys2/cci.latest")else:self.tool_requires("flex/2.6.4")self.tool_requires("bison/3.7.6")

msys2中的C++编译器

上一节说了windows下需要在msys2环境编译,msys2也是可以有自带的c++编译器的。如果msys2中的c++编译器与profile中定义的gcc编译版本不一致。那么erpcgen编译阶段可以正常通过,但在连接过程就会报错。因为依赖库boost的适用版本是按profile中定义的编译器版本提供的。
所以在msys2环境执行编译时不能使用msys2自带的编译器,需要通过CXX环境变量将windows系统安装的g++编译器传递给msys2环境而使用指定的外部编译器。
所以需要在 build_requirements 方法中增加如下逻辑,将在windows shell中获取g++编译器的全路径保存到成员self.cxx_path,注意这个时时候self.win_bash不能为True

    def build_requirements(self):if self._settings_build.os == "Windows":# 获取 windows系统定义的g++编译器位置buf = StringIO()self.run("where g++",stdout=buf)if not buf.getvalue():raise Exception("Not found g++ compiler by 'where gcc'")# 获取命令返回的第一行,删除末尾的换行符self.cxx_path = buf.getvalue().strip().split('\r\n')[0]

然后这个self.cxx_path会在后面的AutotoolsToolchain生成时被定义到CXX环境变量中

generate

erpcgen中需要的编译工具flex,bision的可执行程序,头文件位置,以及boost的位置都是通过环境变量提供给Makefile的。所以需要在 generate 方法中定义相应的环境变量:FLEX,BISON,BOOST_ROOT,INCLUDES
同时还有上一节涉及到的将windows系统下的C++编译器位置通过定义CXX变量提供给msys2环境。
这里使用AutotoolsToolchain实现环境变量修改,与后面的package方法中的Autotools匹配

    def generate(self):tc = AutotoolsToolchain(self)env = tc.environment()if self._settings_build.os == "Windows":# erpcgen中使用环境变量FLEX定义flex,BISON定义bison,# 与winflexbison加载时定义的变量名不一样,所以这里要# 定义环境变量 FLEX=$LEX,BISON=$YACCenv.define('FLEX',self.dependencies.build["winflexbison"].buildenv_info.vars(self).get("LEX"))env.define('BISON',self.dependencies.build["winflexbison"].buildenv_info.vars(self).get("YACC"))include_path = unix_path(self,os.path.join(self.dependencies.build["winflexbison"].package_folder, "include"))# 使用外部定义的C++编译器,避免使用msys2内置的编译器,否则会因为编译版本不一致导致连接错误env.define('CXX',unix_path(self,self.cxx_path))else:# 定义环境变量 FLEX=$LEX,BISON=$BISON_ROOT/bin/bisonenv.define('FLEX',os.path.join(self.dependencies.build["flex"].package_folder,"bin", "flex"))env.define('BISON',self.dependencies.build["bison"].buildenv_info.vars(self).get("CONAN_BISON_ROOT") + "/bin/bison")include_path = os.path.join(self.dependencies.build["flex"].package_folder, "include")# 将 flex的include文件夹添加到INCLUDES环境变量,参见 erpc/erpcgen/Makefile中INCLUDES变量env.append('INCLUDES',include_path)# 指定boost位置boost_root = unix_path(self,self.dependencies["boost"].package_folder)    env.define('BOOST_ROOT',boost_root)env.append('LDFLAGS',"-L" + os.path.join(boost_root,"lib"))tc.generate(env)# 输出环境变量self.output.info("Environment Variables:")for name, value in env.vars(self).items():self.output.info(f"{name}={value}")

package

虽然erpcgen项目不是autools生成的项目,但它可以调用make执行Makefile.所以在此一样可以使用AutotoolsToolchain,Autotools实现编译
如下package方法执行Autotools.install 方法实现 erpcgen编译并安装到package_folder

    def package(self):autotools = Autotools(self)autotools.install(args=["-C", "erpc/erpcgen", "PREFIX={}".format(unix_path(self,self.package_folder))])

完整代码

完整的python代码

from conan import ConanFile,tools
from conan.tools.env import VirtualBuildEnv
from conan.tools.microsoft.subsystems import unix_path
from conan.tools.files import chdir
from conan.tools.gnu import Autotools, AutotoolsToolchain
import os
from six import StringIOclass ErpcgenConan(ConanFile):name = "erpcgen"version = "1.7.3-patch"# Optional metadatalicense = "BSD-2-Clause"author = "guyadong 10km0811@sohu.com"url = "https://gitee.com/l0km/erpcex"description = "erpcgen base NXP Embedded RPC"topics = ("embedded","erpc","nxp","erpcgen")package_type = "application"requires = "boost/[>=1.69.0]"# Binary configurationsettings = "os", "compiler", "build_type", "arch"options = {"shared": [True, False], "fPIC": [True, False]}default_options = {"shared": False, "fPIC": True}# Sources are located in the same place as this recipe, copy them to the recipeexports_sources = "erpc/*"@propertydef _settings_build(self):return getattr(self, "settings_build", self.settings)@propertydef _cxx_path(self):if self._settings_build.os == "Windows":buf = StringIO()self.run("where g++",stdout=buf)if not buf.getvalue():raise Exception("Not found g++ compiler by 'where gcc'")# 获取命令返回的第一行return buf.getvalue().strip().split('\r\n')[0]else:return ""def config_options(self):if self.settings.os == "Windows":del self.options.fPICif self.settings.compiler == "msvc":# 不支持Visual Studio编译,报错退出raise Exception("Unsupport Visual Studio,plese use MinGw compiler for Windows")def build_requirements(self):if self._settings_build.os == "Windows":# 获取 windows系统定义的g++编译器位置buf = StringIO()self.run("where g++",stdout=buf)if not buf.getvalue():raise Exception("Not found g++ compiler by 'where gcc'")# 获取命令返回的第一行self.cxx_path = buf.getvalue().strip().split('\r\n')[0]self.tool_requires("winflexbison/2.5.24")self.win_bash = Trueif not self.conf.get("tools.microsoft.bash:path", check_type=str):# Windows下需要在MSYS2环境编译self.tool_requires("msys2/cci.latest")else:self.tool_requires("flex/2.6.4")self.tool_requires("bison/3.7.6")def generate(self):tc = AutotoolsToolchain(self)env = tc.environment()if self._settings_build.os == "Windows":# erpcgen中使用环境变量FLEX定义flex,BISON定义bison,# 与winflexbison加载时定义的变量名不一样,所以这里要# 定义环境变量 FLEX=$LEX,BISON=$YACCenv.define('FLEX',self.dependencies.build["winflexbison"].buildenv_info.vars(self).get("LEX"))env.define('BISON',self.dependencies.build["winflexbison"].buildenv_info.vars(self).get("YACC"))include_path = unix_path(self,os.path.join(self.dependencies.build["winflexbison"].package_folder, "include"))# 使用外部定义的C++编译器,避免使用msys2内置的编译器,否则会因为编译版本不一致导致连接错误env.define('CXX',unix_path(self,self.cxx_path))else:# 定义环境变量 FLEX=$LEX,BISON=$BISON_ROOT/bin/bisonenv.define('FLEX',os.path.join(self.dependencies.build["flex"].package_folder,"bin", "flex"))env.define('BISON',self.dependencies.build["bison"].buildenv_info.vars(self).get("CONAN_BISON_ROOT") + "/bin/bison")include_path = os.path.join(self.dependencies.build["flex"].package_folder, "include")# 将 flex的include文件夹添加到INCLUDES环境变量,参见 erpc/erpcgen/Makefile中INCLUDES变量env.append('INCLUDES',include_path)# 指定boost位置boost_root = unix_path(self,self.dependencies["boost"].package_folder)    env.define('BOOST_ROOT',boost_root)env.append('LDFLAGS',"-L" + os.path.join(boost_root,"lib"))tc.generate(env)# 输出环境变量self.output.info("Environment Variables:")for name, value in env.vars(self).items():self.output.info(f"{name}={value}")def package(self):autotools = Autotools(self)autotools.install(args=["-C", "erpc/erpcgen", "PREFIX={}".format(unix_path(self,self.package_folder))])

完整的项目参见我的代码仓库:https://gitee.com/l0km/erpcex

conanfile-erpcgen.py 使用示例:

conan create .\conanfile-erpcgen.py 

conan系列文章

《conan入门(一):conan 及 JFrog Artifactory 安装》
《conan入门(二):conan 服务配置-密码管理及策略》
《conan入门(三):上传预编译的库(artifact)》
《conan入门(四):conan 引用第三方库示例》
《conan入门(五):conan 交叉编译引用第三方库示例》
《conan入门(六):conanfile.txt conanfile.py的区别》
《conan入门(七):将自己的项目生成conan包》
《conan入门(八):交叉编译自己的conan包项目》
《conan入门(九):NDK交叉编译自己的conan包项目塈profile的定义》
《conan入门(十):Windows下Android NDK交叉编译Boost》
《conan入门(十一):Linux下Android NDK交叉编译Boost》
《conan入门(十二):Windows NDK 编译 boost报错:CMake was unable to find a build program … MinGW Makefile》
《conan入门(十三):conan info 命令的基本用法》
《conan入门(十四):conan new 命令的新特性–模板功能(–template)》
《conan入门(十五):AttributeError: ‘CMake‘ object has no attribute ‘definitions‘》
《conan入门(十六):profile template功能实现不同平台下profile的统一》
《conan入门(十七):支持android NDK (armv7,armv8,x86,x86_64)交叉编译的统一profile jinja2模板》
《conan入门(十八):Cannot recognize the Windows subsystem, install MSYS2/cygwin or specify a build_require》
《conan入门(十九):封装第三方开源库cpp_redis示例》
《conan入门(二十):封装只包含头文件(header_only)的库示例》
《conan入门(二十一):解决MinGW编译Openssl的编译错误:crypto/dso/dso_win32.c》
《conan入门(二十二):编译 openssl要求python 3.7以上版本》
《conan入门(二十三):Windows下MinGW编译libcurl》
《conan入门(二十四):通过CONAN_DISABLE_CHECK_COMPILER禁用编译器检查》
《conan入门(二十五):imports将包安装到本地项目或其他指定位置》
《conan入门(二十七):因profile [env]字段废弃导致的boost/1.81.0 在aarch64-linux-gnu下交叉编译失败》
《conan入门(二十八):解决conan 1.60.0下 arch64-linux-gnu交叉编译openssl/3.1.2报错问题》
《conan入门(二十九):对阿里mnn进行Conan封装塈conans.CMake和conan.tools.cmake.CMake的区别》
《conan入门(三十):对腾讯ncnn进行Conan封装》
《conan入门(三十一):在命令行(shell)中从profile中读取配置参数》
《conan 入门(三十二):package_info中配置禁用CMakeDeps生成使用项目自己生成的config.cmake》
《conan 入门(三十三):requirements()指定header的可见性(transitive_headers)》
《conan 入门(三十四):conan 2.x实现对只有Makefile的项目(erpcgen)的封装示例》

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

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

相关文章

134. 加油站(贪心算法)

根据题解 这道题使用贪心算法,找到当前可解决问题的状态即可 「贪心算法」的问题需要满足的条件: 最优子结构:规模较大的问题的解由规模较小的子问题的解组成,规模较大的问题的解只由其中一个规模较小的子问题的解决定&#xff…

分享88个节日PPT,总有一款适合您

分享88个节日PPT,总有一款适合您 88个节日PPT下载链接:https://pan.baidu.com/s/1mfLrdlB9Y1jqz2vkVIwBNA?pwd6666 提取码:6666 Python采集代码下载链接:采集代码.zip - 蓝奏云 学习知识费力气,收集整理更不易…

Markdown学习测试

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

国产Type-C接口逻辑协议芯片:Type-C显示器芯片方案

产品介绍 双Type-C盲插选型: LDR6282 PD3.0认证协议芯片,USB-IF TID号:212 支持iic,USB转UART,CC升级方式,多年市场验证,显示器市场出货量,显示器大厂采用兼容性NO.1。采用QFN32 5…

系列十五、SpringBoot的启动原理分析

一、概述 所谓SpringBoot的启动原理,翻译成大白话就是"当我们在主启动类上运行run方法时,SpringBoot底层到底做了什么事情,能够帮助我们启动一个Spring的web应用",上边用大白话解释了一下什么是SpringBoot的启动原理&am…

vue 解决响应大数据表格渲染崩溃问题

如果可以实现记得点赞分享,谢谢老铁~ 1.场景描述 发起请求获取上万条数据,进行表格渲染,使浏览器卡顿,导致网页崩溃。 2.分析原因 1.大量数据加载,过多操作Dom,消耗性能。 2.表格中包含其他…

160. 相交链表

160. 相交链表 考研那段时间记得太牢了。 当然也是简单题。。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {p…

数据库设计实践:粒度的理解与应用示例

粒度是描述数据存储和表示的详细程度。在数据库设计中,理解和正确选择粒度是非常重要的,因为它直接影响到数据的存储效率、查询性能和数据分析的灵活性。 文章目录 粒度的类型:案例粒度选择的考虑因素实际应用 粒度的类型: 细粒度…

24双非硕的秋招总结

24 双非硕的秋招总结 结果: 运气捡漏去了腾讯 想想自己整个研究生学习过程,还是挺坎坷的,记录一下,也给未来的同学提供一些参考。 研一 我是研一上开始学前端的,应该是21年10月份左右,我们实验室是专门…

uniapp前端支付篇(微信、抖音、快手、h5)四个平台支付

前言 微信、快手、h5支付步骤大致相同,只有抖音是有自己的支付组件 项目同时支持多个(微信、快手、h5)平台支付,后端那边代码可以封装的 各平台支付大致流程都是相同的,总结了一下分为五个步骤 点击支付创建订单生成密…

网站更换IP的四大注意事项

1.对网站当中的数据进行备份 网站更换IP时可以将页面的数据库文件和站点文件通过下载工具在本地完成备份。 2.更换解析域名 从站点域名管理后台当中更换域名地址,改为新的IP地址。 3.确保IP安全 在用户更换IP前一定要确定IP是否安全,一旦IP存在不良…

Uniapp Vue3 基础到实战 教学视频

每天都在更新 观看学习地址:视频教学地址(点击跳转) Uniapp的介绍 1 什么是Uniapp?安装及部署 1-1 课程简介: 了解uni-app是什么,它的优势和适用场景,以及它作为一个跨平台框架的基本概念。…

IO流--12--Java lO 设计模式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Java lO 设计模式装饰器模式适配器模式工厂模式观察者模式 Java lO 设计模式 装饰器模式 适配器模式 工厂模式 观察者模式

Kafka常见面试题

如何防止消息丢失? 发送端:ack设置为-1或副本数,默认副本全部同步才会认为发送成功 接收端:对接收到的数据进行备份,定期进行检查对执行失败的数据重新执行;选择手动提交offset,对执行失败的数据…

Windows启动nacos操作文档

Windows启动nacos操作文档 1、新建数据库nacos_config 2、导入nacos\conf\nacos-mysql.sql文件 /******************************************/ /* 数据库全名 nacos_config */ /* 表名称 config_info */ /******************************************/ CREATE T…

【算法】算法题-20231128

这里写目录标题 一、55. 跳跃游戏二、274. H 指数三、125. 验证回文串 一、55. 跳跃游戏 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以&am…

前端监控学习笔记

现成的SDK SentryFun Debug 需要监控什么? 错误统计 记录我们代码发布到线上各种奇奇怪怪的错误 行为日志埋点 记录用户行为,比如:分析用户浏览时间比较长的页面有哪些,常常点击的有哪些,可以做 相应的推荐 PV/UV统…

自定义类型:结构体、联合、枚举

目录 一、⾃定义类型:结构体 1.结构体类型 1. 1结构体类型的声明 结构体变量的创建和初始化 1.2 结构的特殊声明 1.3 结构的自引用 2. 结构体内存对齐 ①:对齐规则 ②:offsetof函数 ③:为什么存在内存对⻬? ④ 修改默认对⻬…

【算法】java写冒泡排序代码

java中把1至9利用冒号排序进行排序的代码怎么写 给你从小到大排序的例子 public void bubbleSort() {System.out.println("冒泡排序:"); int[] array1 = { 9, 8, 7, 6, 5, 4, 3,2,1 }; int i = 0; int j = 0; for (i = 0; i array1.length - 1; i++) {for (j…

基于SpringBoot的驾校管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的驾校管理系统,java项目…