当前位置: 首页 > news >正文

CMake编译proto的方法(custom_target和custom_command)

        最近在项目中涉及到在QNX平台上编译CyberRT,其中CyberRT使用到了protobuf,因此,仓库内部有许多proto文件,需要先行将这些proto文件生成对应的.cc和.h文件才能被其他文件使用。

        之前一直使用protobuf_generate_cpp来编译proto文件,但这个有一个弊端,就是无法控制生成的.cc和.h文件的路径,这个会影响到依赖改proto文件的其他源代码文件的编译,例如a.cpp依赖message.proto,其头文件包含是这样写的

#include "myapplication/proto/message.pb.h"

就是这种和原始proto文件同路径的包含方式,而protobuf_generate_cpp无法将proto生成到这么一个多级路径中。

        因此,这次改用add_custom_command和add_custom_target来完成这个编译。

        思路大致如下:

1. 通过add_custom_target设置一个虚拟的目标文件,其实不会编译处二进制目标文件

2. custome_target依赖custom_command中的输出

3.通过custom_command手动调用protoc来编译proto,通过--cpp_out, -I以及proto文件控制生成的.pb.h, .pb.cc文件的路径

        CMake写法如下:

file(GLOB PROTO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.proto)set(PROTO_DIR ${CMAKE_BINARY_DIR}/proto/message)  # 生成文件的路径if(EXISTS ${PROTO_DIR} AND IS_DIRECTORY ${PROTO_DIR})  # 创建上面路径对应的目录message(info " ${PROTO_DIR} ALREADY EXISTS")
else()file(MAKE_DIRECTORY ${PROTO_DIR})
endif()foreach(proto ${PROTO_FILES}    # 对每个proto文件执行protocget_filename_component(FILE_WE ${proto} NAME_WE)list(APPEND PROTO_SRCS ${PROTO_DIR}/${FILE_WE}.ph.cc)  # 更新pb.cc文件列表list(APPEND PROTO_HDRS ${PROTO_DIR}/${FILE_WE}.ph.h)   # 更新ph.h文件列表add_custom_command(OUTPUT "${PROTO_DIR}/${FILE_WE}.ph.cc""${PROTO_DIR}/${FILE_WE}.ph.h"COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}ARGS --cpp_out ${PROTO_DIR}-I ${CMAKE_BINARY_DIR}/proto/message${proto}DEPENDS ${proto}COMMENT "Running protoc on proto file ${proto}"VERBATIM
endforeach()add_custom_target(generate_proto_rule ALLDEPENDS ${PROTO_SRCS} ${PROTO_HDRS}COMMENT "build generate_proto_rule target"VERBATIM
)

        其中,PROTOBUF_PROTOC_EXECUTABLE需要在cmake命令中通过-D手动指定protoc二进制的路径。

相关文章:

  • 03- jQuery事件处理和动画效果
  • 【漏洞复现】致远互联FE协作办公平台 ncsubjass SQL注入
  • 切割游戏介绍
  • 代码审计中XSS挖掘一些体会
  • MySQL数据库回顾(1)
  • 构建LangChain应用程序的示例代码:37、基于LangGraph的文档检索与答案生成系统教程
  • 在VS Code中快速生成Vue模板的技巧
  • 查看 RK3568 Android SDK 版本的详细指南
  • 猫头虎分享已解决Bug || 前端领域技术问题解析
  • 常见的网络设备
  • Java算法常用技巧
  • web前端之vue一键部署的shell脚本和它的点.bat文件、海螺AI、ChatGPT
  • 基于PHP的草莓种植信息管理系统
  • SpringCloud学习笔记 - 1、Boot和Cloud版本选型
  • 代码规范性思考
  • Django 博客开发教程 8 - 博客文章详情页
  • ERLANG 网工修炼笔记 ---- UDP
  • HTTP那些事
  • Java,console输出实时的转向GUI textbox
  • javascript 总结(常用工具类的封装)
  • Java的Interrupt与线程中断
  • js ES6 求数组的交集,并集,还有差集
  • Laravel核心解读--Facades
  • maven工程打包jar以及java jar命令的classpath使用
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • Object.assign方法不能实现深复制
  • Spring框架之我见(三)——IOC、AOP
  • webpack入门学习手记(二)
  • 从PHP迁移至Golang - 基础篇
  • 第十八天-企业应用架构模式-基本模式
  • 机器学习 vs. 深度学习
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 我看到的前端
  • 自动记录MySQL慢查询快照脚本
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • !$boo在php中什么意思,php前戏
  • #单片机(TB6600驱动42步进电机)
  • (1)Android开发优化---------UI优化
  • (13)DroneCAN 适配器节点(一)
  • (16)Reactor的测试——响应式Spring的道法术器
  • (4) PIVOT 和 UPIVOT 的使用
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (区间dp) (经典例题) 石子合并
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .net 按比例显示图片的缩略图
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • // an array of int
  • @开发者,一文搞懂什么是 C# 计时器!
  • [2023-年度总结]凡是过往,皆为序章
  • [android] 天气app布局练习