Tahmm
Tahmm

Reputation: 43

Is there a way to specify output imports for generated C++ code when using ProtocolBuffers?

I'm trying to compile C++ code into a single binary using .proto files. My current process has 2 steps;

  1. Generate C++ code from 3 .proto files using protoc.
  2. Compile the generated code and my own C++ code into a single .o file.

However, when I try to compile in step 2, the generated code specified outputs as 'com/company/B.pb.h', which fails to be found by the compiler, because the file is in the same directory.

I don't want to manually change the generated code imports as I feel that should be done by protoc, and we also use these proto files for other projects (including generating java code using the same .proto files, which works). Is there a way to specify the generated code's imports WITHOUT changing the proto imports?

EDIT: Is this an issue with protoc when generating multiple files at once? Should I be using a different command?

I know there are options for java like specifying the package or classname, but I can't find anything similar for C++.

option java_multiple_files = true;
option java_package = "com.company.B";
option java_outer_classname = "B";

Any help is much appreciated. More details below.

Directory structure:

.
├── com
│   └── company # generated code
│       ├── A.pb.cc
│       ├── A.pb.h
│       ├── B.pb.cc
│       ├── B.pb.h
│       ├── C.pb.cc
│       └── C.pb.h
├── Parser.cc
├── Parser.h
└── proto
    └── com
        └── company
            ├── A.proto
            ├── B.proto
            └── C.proto

Protoc command: (run from .)

protoc --cpp_out=. --proto_path=proto/ com/company/A.proto com/company/B.proto com/company/C.proto

A.proto snippet:

syntax = "proto3";
option optimize_for = SPEED;

package com.company;

import "com/company/B.proto"; # specified as full path re Google's documentation

...

Parser.cc:

#include "parser.h"
...

Parser.h:

#include "com/company/A.pb.h"
#include "com/company/B.pb.h"
#include "com/company/C.pb.h"
...

G++ command:

g++ -fPIC -Lprotoc -lprotobuf parser.cc -o parser.so

The Error:

fatal error: com/company/B.pb.h: No such file or directory
 #include "com/company/B.pb.h"
          ^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

Upvotes: 2

Views: 741

Answers (1)

Tahmm
Tahmm

Reputation: 43

I never found a way to specify the output for C++ generated code, but I found a way to compile the code correctly without doing janky workarounds, and I think this is the approach I should have taken at the start. Here goes:

Step 1, the generated C++ code stays the same, and it is generated with path includes, and are compiled in the same directory.

Step 2 becomes a make file (we are using Ruby Make/Rake but the concept is the same) The makefile specifies;

  • the parser.cc and all the generated .cc files as the sources.
  • the $LIBS flags -fPIC -lprotobuf (Note the lack of -Lprotoc here, I ran into errors further along the track. Usually about undefined symbols)
  • the $INCFLAGS ` -I$(srcdir)/com/company ```. (This is a directory for the make file to include in compilation)
  • the $VPATH $(srcdir)/com/company. (This is a directory for the make file to search.)

This resulted in a .o file being generated for each .proto file, and a .o file for the parser.cc. Then they are combined into a single .so file which can be used as we intended.

Feel free to ask questions if you run into similar issues.

Upvotes: 0

Related Questions