rose在用的protobuf版本:protobuf-21.8(2022-10-18)。下一版本是protobuf-21.9,但该版本依赖abseil,protobuf-21.8也就成了不须要abseil的最后版本。
一、编译
在windows,运行cmake,便可生成图1的protobuf.sln,编译它就可编译出protobuf。到protobuf-21.9后,开始依赖abseil,编译就变困难了。

1.1 protoc.exe
在windows,编译出图1中所有项目,生成的结果就有protoc.exe。
对rose,配套的protoc.exe放在<apps-src>/scritps,并增加相应版本号:protoc-3.21.8.exe。
1.2 protobuf-lite
cmake生成出的libprotobuf有两种库,libprotobuf、libprotobuf-lite,它们区别可参考“protobuf-lite的使用C++ 及 windows 平台内存泄露解决方法”。
protobuf虽然很好,还有一个问题,NDK编译出的Lib SO 近20M,如果在android 上使用,明显不合适。造成包体积过大。
所以想到了protobuf-lite,相对体积减小十倍。
要运行只需protobuf-lite的protobuf也很简单,修改*.proto文件,添加option optimize_for = LITE_RUNTIME;
optimize_for是文件级别的选项,Protocol Buffer定义三种优化级别SPEED/CODE_SIZE/LITE_RUNTIME。默认是SPEED。
- SPEED: 表示生成的代码运行效率高,但是由此生成的代码编译后会占用更多的空间。
- CODE_SIZE: 和SPEED恰恰相反,代码运行效率较低,但是由此生成的代码编译后会占用更少的空间,通常用于资源有限的平台,如Mobile。
- LITE_RUNTIME: 生成的代码执行效率高,同时生成代码编译后的所占用的空间也是非常少。这是以牺牲Protocol Buffer提供的反射功能为代价的。因此我们在C++中链接Protocol Buffer库时仅需链接libprotobuf-lite,而非libprotobuf。在Java中仅需包含protobuf-java-2.4.1-lite.jar,而非protobuf-java-2.4.1.jar。
SPEED和LITE_RUNTIME相比,在于调试级别上,例如 msg.SerializeToString(&str) 在SPEED模式下会利用反射机制打印出详细字段和字段值,但是LITE_RUNTIME则仅仅打印字段值组成的字符串;
理论上说,如果书写proto都用上了“optimize_for = LITE_RUNTIME”,那用体积小的protobuf-lite就够了。但rose集成的是libprotobuf,原因是rose要处理一些含有proto的开源库,像opencv,webrtc、cartographer。当中有的*.proto没使用LITE_RUNTIME,编译成libprotobuf可避免修改它们。
如果是你自已写protco,加optimize_for = LITE_RUNTIME,即使用的是libprotobuf,还是会执行“LITE_RUNTIME”优化。
二、cartographer中的proto
cartographer中有不少proto文件,有些间还存在关联,protoc.exe处理时不是一个“--cpp_out”参数就够的。
<cartographer>/proto-new-one.bat ------ set SCRIPTS=c:\ddksample\apps-src\scripts set CARTOGRAPHER=C:\ddksample\apps-src\apps\external\libros\cartographer set CUR_DIR=C:\ddksample\apps-src\apps\external\libros\cartographer\cartographer\ground_truth\proto cd %CUR_DIR% %SCRIPTS%\protoc-3.21.8.exe --proto_path=%CARTOGRAPHER% --proto_path=%CUR_DIR% --cpp_out=. relations.proto
这是处理单独一个proto文件方法,除“--cpp_out”,还使用“--proto_path”。但对cartographer中所有proto做这样处理后,对应*.pb.h、*.pb.cc都生成了,但编译cartographer时出现众多类似下面错误。
3><cartographer>mapping\proto\grid_2d.pb.cc(124,6): error C2039: 'descriptor_table_cartographer_2fmapping_2fproto_2fmap_5flimits_2eproto': is not a member of '`global namespace'' 3><cartographer>mapping\proto\grid_2d.pb.cc(124,76): error C2065: 'descriptor_table_cartographer_2fmapping_2fproto_2fmap_5flimits_2eproto': undeclared identifier
按错误提示,是没定义全局变量“descriptor_table_cartographer_2fmapping_2fproto_2fmap_5flimits_2eproto”。我的解决办法是把全局变量“descriptor_table_map_5flimits_2eproto”改为它。我怎知道是“descriptor_table_map_5flimits_2eproto”?——在用protoc-3.14.0.exe时,曾知道它们对应关系。不过在protoc-3.14.0.exe时,又遇到过其它问题,还是得得花时间额外解决。
如何一次就生成正确*.pb.h、*.pb.cc?——是protoc-3.21.8.exe时参数不对还是其它,只能等熟悉protobuf的人来解决了。
“descriptor_table_cartographer_2fmapping_2fproto_2fmap_5flimits_2eproto”只是众多中一个,还是其它的,像descriptor_table_cartographer_2ftransform_2fproto_2ftransform_2eproto,差不多近40处。