protobuf_generate() seems to be generating incorrect paths. Usage error or bug?

I’m working on a larger project which currently performs in-tree out-of-build protobuf generation. I’m looking at converting to using in-build protobuf generation with CMake’s support. Unfortunately, I’m running into issues where protobuf_generate() seems to attempt to use incorrect paths. Hopefully this is a usage issue. If not, I can see about filing a ticket.

I’m currently using cmake 3.30.5

I’ve created a minimal testcase with the directory hierarchy:

  • builds
  • libs
    • proto_build
      • CMakeLists.txt
  • protos
    • proto-base
      • proto_component
        • test.proto
  • CMakeLists.txt

The contents:
CMakeLists.txt:

cmake_minimum_required(VERSION 3.22.1)
project(cmake_demo VERSION 0.0.1)
set(ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
add_subdirectory(libs/proto_build)

libs/proto_build/CMakeLists.txt:

project(ProtoBuildProject)
find_package(Qt6 COMPONENTS Core Network REQUIRED)
find_package(Protobuf)
file(GLOB_RECURSE PROTO_FILES "${ROOT_DIR}/protos/proto-base/proto_component/*.proto")
add_library(proto-build-proto-lib)
protobuf_generate(
    TARGET proto-build-proto-lib
    LANGUAGE cpp
    OUT_VAR BUILD_PROTO_OUT_FILES
    EXPORT_MACRO "EXPORT_MACRO"
\#   PROTOC_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/proto/build/src"
    PROTOC_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}"
   PROTOS ${PROTO_FILES}
    IMPORT_DIRS "${ROOT_DIR}/protos/"
)

protos/proto-base/proto_component/test.proto:

syntax = "proto3";
package proto_component;
message TestProto
{
    string s = 1;
    int32 i = 2;
}

I run cmake with:

/home/developer/Qt/Tools/CMake/bin/cmake -S /home/developer/cmake_demo -B /home/developer/cmake_demo/builds/Debug -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++ -DCMAKE_GENERATOR:STRING=Ninja

My expectation is that I would have the relevant .pb.cc and .pb.h files created, compiled and linked into a library. Instead, I end up with path mismatches.

First, the files are created. They can be found at:

  • /home/developer/cmake_demo/builds/Debug/libs/proto_build/proto-base/proto_component/test.pb.cc
  • /home/developer/cmake_demo/builds/Debug/libs/proto_build/proto-base/proto_component/test.pb.h

However, the attempt to build them fails. I get:

$ ninja
FAILED: libs/proto_build/CMakeFiles/proto-build-proto-lib.dir///protos/proto-base/proto_component/test.pb.cc.o
/usr/bin/g++ -O2 -pipe -g -feliminate-unused-debug-types -g -MD -MT libs/proto_build/CMakeFiles/proto-build-proto-lib.dir///protos/proto-base/proto_component/test.pb.cc.o -MF libs/proto_build/CMakeFiles/proto-build-proto-lib.dir///protos/proto-base/proto_component/test.pb.cc.o.d -o libs/proto_build/CMakeFiles/proto-build-proto-lib.dir///protos/proto-base/proto_component/test.pb.cc.o -c /home/developer/cmake_demo/builds/Debug/protos/proto-base/proto_component/test.pb.cc
cc1plus: fatal error: /home/developer/cmake_demo/builds/Debug/protos/proto-base/proto_component/test.pb.cc: No such file or directory

So it looks like it builds the .pb.cc/.pb.h files in the specified PROTOC_OUT_DIR directory, but then looks for them to be in the source directory.

As a related issue, I noticed that the PROTOC_OUT_DIR parameter doesn’t work if the specified directory doesn’t exist. If I swap out the commented-out version above to place the generated files in subdirectory of ${CMAKE_CURRENT_BINARY_DIR} which currently doesn’t exist, the build will fail due to the directory not existing.

Please let me know if I’ve done something obviously-wrong here which can be worked around.

I don’t have the time at the moment to fully debug your example, but I’ve done a hello-world example for protobuf_generate() in the context of gRPC before that may be useful to you.

Hi!

Thanks for the response. I suspect that the issue is related to the proto files being in a different directory tree from the child CMakeLists.txt file leading to path generation issues. The example you provided seems to have the code organized in simpler and more coherent structure than the one I am dealing with.