无法编译 protoc 生成的 (C++) 类

Cannot compile protoc-generated (C++) classes

本文关键字:C++ 编译 protoc      更新时间:2023-10-16

我目前在编译 protobuf 生成的C++代码时遇到了一些麻烦。protoc运行正常并且不显示任何警告,但是当我尝试编译生成的C++代码以便构建静态库时,g++ 向我显示以下消息:

CanInfo.pb.cc:107:5:错误:"::p rotobuf_BusType_2eproto' 尚未声明 107 | ::p rotobuf_BusType_2eproto::AddDescriptors((;

到目前为止,我能够收集到的内容是我的 BusType 枚举的一些问题,它看起来像这样:

syntax = "proto3";
package MyPackage;
enum BusType {
ProprietaryBus = 0;
OpenBus = 1;
UnknownBus = 2;
}

此枚举包含在名为 CanInfo(如 CanInfo(的消息中,该消息如下所示:

syntax = "proto3";
package MyPackage;
import "BusType.proto";
message CanInfo {
int32 interfaceId = 10;
bool isConnected = 20;
BusType busType = 30;
}

正如我之前提到的,protoc"正确"编译这些文件(没有错误(。 用于编译 protos 的版本是protoc 3.6.0。 这是protoc生成的C++代码部分:

::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
descriptor, 248);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"data_containers/device_data/CanInfo.proto", &protobuf_RegisterTypes);
::protobuf_BusType_2eproto::AddDescriptors();
//           ^ error occurs here

搜索代码,唯一提到protobuf_BusType_2eproto命名空间的是上面的行。 用于编译C++代码的编译器版本是powerpc-linux-gnu-g++-6 (Ubuntu 6.4.0-17ubuntu1) 6.4.0 20180424。 将用于版本 8 或 9 的 G++ 版本更改为此行为不会更改此行为。

我已经尝试多次清理构建目录,并尝试切换到不同的protobuf版本(3.4.0(,但是这也导致了许多编译器错误,主要是因为protoc版本太旧了。

单独构建每个文件也不会改变行为。

是什么导致了这种行为?到目前为止,我在使用 Protobuf 时还没有遇到任何问题。 以前有没有人经历过这种情况并知道一个方便的技巧?


编辑这可能是由我打电话给protoc的方式引起的吗?

###
# Re-compile protos
###
set(BUILD_PROTOS True)
set(PROTOBUF_COMPILER protoc)
if (BUILD_PROTOS)
function(BUILD_PROTOS)
foreach(PROTO ${PROTOS})
message("Compiling ${PROTO}...")
execute_process(
COMMAND ${PROTOBUF_COMPILER} ${PROTO_DIRS} "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" ${PROTO}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endforeach()
endfunction()
###
# Compile all protos
###
BUILD_PROTOS()
endif()

似乎我已经解决了这个问题。protoc编译器中显然存在一个错误,每次编译单个文件时,在同一目录中导入文件会导致这种奇怪的行为。 一次编译多个文件时,protoc会产生一个错误,指出枚举值已在另一个文件中定义,并发出以下注释:

device_data/BusType.proto:15:5:请注意,枚举值使用C++范围规则,这意味着枚举值是其类型的同级,而不是其子级。 因此,"ProprietaryBus"在"MyPackage"中必须是唯一的,而不仅仅是在"BusType"中。

谷歌搜索愈演愈烈,我看到了2012年的这个旧的谷歌代码帖子:

协议编译器"bar.proto">

和"x/bar.proto"是两个原型文件
,尽管它们指向同一个物理文件。
使用"import 'x/bar.proto'"是正确的解决方法。

解决方法(或修复(只是添加相对于protoc的工作目录的整个路径。

import "data_containers/device_data/BusType.proto";

在CMake中,现在如下所示。

message("Compiling protos...")
execute_process(
COMMAND ${PROTOBUF_COMPILER}
${PROTO_DIRS} "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" ${PROTOS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

到目前为止,这已经解决了我的问题,如果出现任何新信息,我将编辑我的答案。 也许这对其他人有用。