使用Protobuf2的项目引入依赖Protobuf3的TensorFlow C-API报错如何解决
错误说明
你遇到的是典型的多版本Protobuf符号冲突问题,错误如下:
libprotobuf FATAL google/protobuf/stubs/common.cc:61] This program requires version 3.9.0 of the Protocol Buffer runtime library, but the installed version is 2.6.1. Please update your library. If you compiled the program yourself, make sure that your headers are from the same version of Protocol Buffers as your link-time library. (Version verification failed in "bazel-out/k8-opt/bin/tensorflow/core/framework/tensor_shape.pb.cc".)
terminate called after throwing an instance of 'google::protobuf::FatalException'
what(): This program requires version 3.9.0 of the Protocol Buffer runtime library, but the installed version is 2.6.1. Please update your library. If you compiled the program yourself, make sure that your headers are from the same version of Protocol Buffers as your link-time library. (Version verification failed in "bazel-out/k8-opt/bin/tensorflow/core/framework/tensor_shape.pb.cc")
可行修复方案
方案1:隐藏TensorFlow内部Protobuf符号(最推荐,零改动原有业务代码)
这个方案不需要修改你原有Protobuf2的任何代码,只需要调整CMake链接参数即可:
- 原因:预编译的TensorFlow C API已经将Protobuf 3.9.0静态编译到自身内部,只是默认会导出Protobuf相关的全局符号,和你项目链接的Protobuf 2.6.1的符号冲突,触发版本校验报错
- CMake配置修改:在链接TensorFlow库的目标配置中,添加对应平台的链接选项:
- Linux平台:添加
-Wl,--exclude-libs,libprotobuf.a参数,仅隐藏Protobuf静态库的全局符号,也可以用-Wl,--exclude-libs,ALL隐藏所有静态链接库的符号,不会影响正常功能
target_link_options(你的项目目标名 PRIVATE -Wl,--exclude-libs,ALL)- macOS平台:添加
-Wl,-hidden-lprotobuf参数即可
- Linux平台:添加
- 验证:重新编译后不会再触发版本校验报错,两个版本的Protobuf分别在TensorFlow内部和你的项目逻辑中独立运行,互不干扰
方案2:全项目切换到Protobuf 3.9.0,保留Proto2语法(次推荐,改动量极小)
你提到的给旧proto文件添加syntax="proto2"声明的方案完全可行:
- Protobuf 3.x版本100%兼容Proto2语法,只要给所有旧
.proto文件的第一行添加syntax = "proto2";声明,生成的C++代码接口和Protobuf 2.6.1生成的接口几乎完全一致,99%的业务代码不需要任何修改 - 仅需要注意将整个项目的Protobuf依赖统一更换为3.9.0版本,确保头文件和链接的库版本完全匹配,不要混用2.6.1的头文件即可
方案3:独立封装TensorFlow调用逻辑(不推荐,维护成本高)
如果一定要在项目中同时保留两个版本的Protobuf,可以将所有TensorFlow相关的调用逻辑封装为一个独立的动态库:
- 该动态库编译时静态链接Protobuf 3.9.0,并且将所有Protobuf相关的符号设置为隐藏,不对外导出
- 主项目只调用该封装动态库的纯C接口,完全不接触TensorFlow内部的Protobuf结构,即可避免符号冲突
- 该方案需要额外做封装逻辑,维护成本高于前两个方案,仅在前两个方案无法落地时使用
内容的提问来源于stack exchange,提问作者Emilio7773

