静态链接libprotobuf.a报ZeroFieldsBase未定义引用问题咨询
问题根因
这是Protobuf 21.1版本autotools构建脚本的已知缺陷:该版本中ZeroFieldsBase类的实现源文件generated_message_bases.cc仅会被编译进动态库libprotobuf.so,不会被打包进静态库libprotobuf.a。静态链接时,无任何字段的proto生成的代码会派生自ZeroFieldsBase,自然会抛出该类vtable未定义的引用错误;而带字段的proto派生自Message类,对应符号已经存在于静态库中,因此可以正常链接。
解决方法
按优先级从高到低选择任意一种方案即可:
- 升级Protobuf版本到21.4及以上,官方已经在该版本修复了autotools构建静态库时的符号遗漏问题,重新编译安装后即可正常链接。
- 保留当前Protobuf 21.1版本,重新编译时追加configure参数关闭动态库构建,强制所有实现代码打包进静态库:
配置完成后依次执行./configure --prefix=/usr/local --disable-shared --enable-static --with-picmake clean、make -j$(nproc)、make install重新安装,再重新构建你的项目即可。 - 保留当前Protobuf 21.1版本,改用CMake方式编译安装,CMake构建脚本不存在该静态库符号遗漏问题,编译完成后可正常链接。
- 临时规避方案:如果暂时不方便重新编译Protobuf,可以在无字段的message中添加保留字段占位,比添加虚假业务字段更规范,也不会破坏消息定义的兼容性,让proto编译器不再将该消息派生自
ZeroFieldsBase:
注意该方案只是临时规避手段,没有从根源解决静态库符号缺失的问题,后续项目中新增其他无字段proto时还是会触发同样的链接错误。syntax = "proto2"; package proj.cfg; message Foo { enum Type { ONE = 1; TWO = 2; THREE = 3; } reserved 1; // 占位规避ZeroFieldsBase静态链接问题 }
内容的提问来源于stack exchange,提问作者Steve Lorimer
相关产品推荐
相关产品推荐

