I'm currently having some troubles with compiling protobuf-generated C++ code.
protoc
runs correctly and doesn't show any warnings, however when I try to compile the generated C++ code so I can build a static library, g++ shows me the following message:
CanInfo.pb.cc:107:5: error: ‘::protobuf_BusType_2eproto’ has not been declared 107 | ::protobuf_BusType_2eproto::AddDescriptors();
What I've been able to gather so far, this is some issue with my BusType enumeration, which looks something like this:
syntax = "proto3";
package MyPackage;
enum BusType {
ProprietaryBus = 0;
OpenBus = 1;
UnknownBus = 2;
}
This enumeration is included by a message called CanInfo which looks something like this:
syntax = "proto3";
package MyPackage;
import "BusType.proto";
message CanInfo {
int32 interfaceId = 10;
bool isConnected = 20;
BusType busType = 30;
}
As I mentioned before, protoc
compiles these files "correctly" (without error).
The version used to compile the protos is protoc 3.6.0.
This is the portion of C++ code generated by protoc
:
::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
Searching through the code, the only mention of the protobuf_BusType_2eproto
namespace is the line above.
The compiler version used to compile the C++ code is powerpc-linux-gnu-g++-6 (Ubuntu 6.4.0-17ubuntu1) 6.4.0 20180424
.
Changing the G++ version used to version 8 or 9 doesn't change this behaviour.
I've tried cleaning the build directory many times, and I've tried switching to a different protobuf version (3.4.0), however this also resulted in many compiler errors, mostly because the protoc
version was too old.
Building each file individually also doesn't change the behaviour.
What is causing this behaviour? I've not had issues using Protobuf until now. Has anyone experienced this before and knows a handy trick?
EDIT
Could this possibly be caused by the way I'm calling 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()
It seems as though I've fixed the issue.
There is apparently a bug in the protoc
compiler, where importing files in the same directory causes this strange behaviour when compiling single files each time.
When compiling multiple files at once, protoc
produces an error stating that the enum value has already been defined in another file and issues the following note:
device_data/BusType.proto:15:5: Note that enum values use C++ scoping rules, meaning that enum values are siblings of their type, not children of it. Therefore, "ProprietaryBus" must be unique within "MyPackage", not just within "BusType".
The googling intensified and I came across this old Google Code post from 2012:
To protocol compiler "bar.proto" and "x/bar.proto" are two proto files
although they are pointed at the same physical file.
Using 'import "x/bar.proto"' is the right fix.
The workaround (or fix) was simply to add the entire path relative to the working directory of protoc
.
import "data_containers/device_data/BusType.proto";
In CMake, this looks like the following now.
message("Compiling protos...")
execute_process(
COMMAND ${PROTOBUF_COMPILER}
${PROTO_DIRS} "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" ${PROTOS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
This has so far fixed my problem, I will edit my answer if any new information comes up. Maybe this will be useful to someone else.