尝试使用对protobuffers 2.6.1和3.4.1的引用来编译代码

时间:2018-06-06 15:59:20

标签: c++ cmake protocol-buffers ros

我正在尝试编译单个代码库,引用protobuffers 3.4.1和2.6.1。现在2.6.1变体是全局定义的,因为我使用的是ubuntu xenial,也是:

$ protoc --version

的产率:

libprotoc 2.6.1

protobuffer版本3.4.1的要求来自Google Cartographer(https://github.com/googlecartographer/cartographer),而2.6.1的要求来自转子模拟器(https://github.com/ethz-asl/rotors_simulator),因为它依赖于Gazebo-7(使用它) protobuffer 2.6.1)。为了编译Google Cartographer,我已经通过添加以下内容为Google Cartographer调整CMakeList.txt(请参阅此处的原始文件:https://raw.githubusercontent.com/googlecartographer/cartographer/master/CMakeLists.txt),将二进制文件(在proto3文件夹中添加,见下文)添加到安装中行:

set(CMAKE_PREFIX_PATH CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/proto3")
...
install(DIRECTORY proto3/ DESTINATION .)

因此,protobuffer 3.4.1的二进制文件被添加到安装文件夹中。我正在利用catkin-tools(https://catkin-tools.readthedocs.io/en/latest/)来构建整个工作区。现在在转子模拟器的CMakelist.txt中,我有以下一行:

find_package(Protobuf 2.6.1 REQUIRED HINTS "/usr")

但是在尝试编译时,它似乎无法找到protobuffer 2.4.1,因为它返回以下内容:

Could not find a configuration file for package "Protobuf" that is
compatible with requested version "2.6.1".

The following configuration files were considered but not accepted:

/home/jochem/catkin_ws/install/lib/cmake/protobuf/protobuf-config.cmake, 
version: 3.4.1

作为旁注,如果我单独编译包,我就可以编译和安装包。这可以通过以下命令完成:

 catkin build cartographer_ros 

 catkin build rotors_gazebo_plugins

我目前正在尝试调整rotors_gazebo_plugins的包,但到目前为止还没有成功确保选择了正确的protobuffer库,我是否通过定义对本地protobuffer版本的引用而遗漏了一些东西?

2 个答案:

答案 0 :(得分:1)

你会发现可以在mac上构建一个引用同一个库的2个版本的单个可执行文件,在windows上相当困难,而在unix上几乎不可能。这是因为两个库之间的符号名称不同,所以如果你加载这两个库,就无法知道哪个库应该为哪个调用服务。

如果要在一个makefile包中构建2个不同的可执行文件,那么您只需要在链接阶段设置要加载的正确库。在linux中,库通常安装在具有版本号后缀的系统上,以及发布没有版本号的最新版本的符号链接。通常,您只需链接到未添加的最新版本,但在您的情况下,在您的链接命令中,您需要显式添加后缀。

如果你真的需要将这个cobble-together链接到一个可执行文件中,在unix上你可以用objcopy --redefine-syms做很多事情来重命名其中一个库中的所有入口点,以及依赖项中的所有引用在编译之后但在链接之前编码。请注意,预期的最终结果是两个库将独立运行,并且不会彼此了解。

答案 1 :(得分:0)

如果你能够将至少一个lib(即Cartographer或Rotors或两者)包装到一个单独的共享库中,并且如果protobuff仅在内部用于每个lib,你仍然可以通过使用-fvisibility=hidden gcc标志构建共享库(以切换默认可见性以隐藏符号)并仅通过{{1导出所需的符号(应用程序正在使用)来在单个可执行文件中使用它们}}

这种方式我记得我过去在同一个应用程序中使用了两个完全不同的Boost版本(共享库没有导出静态链接的boost符号)。