make cannot find the Protobuf include headers

I’m trying to get a tiny test with Protobuf to compile and cannot figure out why this fails. I tried to upload the code, but don’t have the rights, so bear with me when I add the code to this post.

I have the Protobuf source in the subfolder “proto”

The root has the following CMakeLists.txt

cmake_minimum_required(VERSION 3.14)

project(MyProtoBuffTest LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)

ADD_SUBDIRECTORY(proto)

include_directories(${Protobuf_INCLUDE_DIRS})

add_executable(MyProtoBuffTest
  main.cpp
)
target_link_libraries(MyProtoBuffTest Qt${QT_VERSION_MAJOR}::Core)

include(GNUInstallDirs)
install(TARGETS MyProtoBuffTest
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

The CMakeLists.txt in the proto subfolder looks like this. Please ignore my ‘debug’

FIND_PACKAGE(Protobuf REQUIRED)
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER message.proto)
ADD_LIBRARY(proto ${PROTO_HEADER} ${PROTO_SRC})

#PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER message.proto)
#ADD_LIBRARY(proto ${PROTO_HEADER} ${PROTO_SRC})
#include_directories(${CMAKE_BINARY_DIR}/proto)

message("   --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}")
message("   --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}")
message("   --> PROTOBUF VERSION: ${Protobuf_VERSION}")
message("   --> PROTOBUF Found: ${Protobuf_FOUND}")
message("   --> PROTOBUF SRC: ${PROTO_SRC}")
message("   --> PROTOBUF HEADER: ${PROTO_HEADER}")
message("   --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto")


include_directories(${CMAKE_CURRENT_BINARY_DIR})

get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
  message(STATUS "directory is ='${dir}'")
endforeach()

The cmake output is as follows

-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Performing Test HAVE_STDATOMIC
-- Performing Test HAVE_STDATOMIC - Success
-- Found WrapAtomic: TRUE  
-- Found Protobuf: /usr/lib/x86_64-linux-gnu/libprotobuf.so (found version "3.12.4") 
   --> PROTOBUF LIB: /usr/lib/x86_64-linux-gnu/libprotobuf.so
   --> PROTOBUF INCLUDE: /usr/include
   --> PROTOBUF VERSION: 3.12.4
   --> PROTOBUF Found: TRUE
   --> PROTOBUF SRC: /home/llist/QtProjects/MyProtoBuffTest/build/proto/message.pb.cc
   --> PROTOBUF HEADER: /home/llist/QtProjects/MyProtoBuffTest/build/proto/message.pb.h
   --> PROTOBUF Folder: /home/llist/QtProjects/MyProtoBuffTest/build/proto
-- directory is ='/home/llist/QtProjects/MyProtoBuffTest/build/proto'
-- Configuring done
-- Generating done
-- Build files have been written to: /home/llist/QtProjects/MyProtoBuffTest/build

the make output is

[ 10%] Automatic MOC and UIC for target MyProtoBuffTest
[ 10%] Built target MyProtoBuffTest_autogen
[ 20%] Building CXX object CMakeFiles/MyProtoBuffTest.dir/MyProtoBuffTest_autogen/mocs_compilation.cpp.o
[ 30%] Building CXX object CMakeFiles/MyProtoBuffTest.dir/main.cpp.o
/home/llist/QtProjects/MyProtoBuffTest/main.cpp:2:10: fatal error: proto/message.pb.h: No such file or directory
    2 | #include "proto/message.pb.h"
      |          ^~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/MyProtoBuffTest.dir/build.make:90: CMakeFiles/MyProtoBuffTest.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:102: CMakeFiles/MyProtoBuffTest.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

The “proto/message.pb.h” file did get generated by cmake, but I’d appreciate if somebody could point out why the compiler can’t find it.

include_directories only affects targets made after it was called. Swap the order of these two.

Thanks Ben.
Have made the suggested change, but still no success.
I removed the include for the protobuf generated header and just ran the generation of the protobuf files and noticed

${Protobuf_INCLUDE_DIRS} still points to “/usr/include”. Is this something I need to specify?

llist@poldis:~/QtProjects/MyProtoBuffTest/build$ cmake ..
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Performing Test HAVE_STDATOMIC
-- Performing Test HAVE_STDATOMIC - Success
-- Found WrapAtomic: TRUE  
-- Found Protobuf: /usr/lib/x86_64-linux-gnu/libprotobuf.so (found version "3.12.4") 
   --> PROTOBUF LIB: /usr/lib/x86_64-linux-gnu/libprotobuf.so
   --> PROTOBUF INCLUDE: /usr/include
   --> PROTOBUF VERSION: 3.12.4
   --> PROTOBUF Found: TRUE
   --> PROTOBUF SRC: /home/llist/QtProjects/MyProtoBuffTest/build/proto/message.pb.cc
   --> PROTOBUF HEADER: /home/llist/QtProjects/MyProtoBuffTest/build/proto/message.pb.h
   --> PROTOBUF Folder: /home/llist/QtProjects/MyProtoBuffTest/build/proto
  This is where the include directories should be listed
-- Configuring done
-- Generating done
-- Build files have been written to: /home/llist/QtProjects/MyProtoBuffTest/build
llist@poldis:~/QtProjects/MyProtoBuffTest/build$ make
[ 10%] Automatic MOC and UIC for target MyProtoBuffTest
[ 10%] Built target MyProtoBuffTest_autogen
[ 20%] Building CXX object CMakeFiles/MyProtoBuffTest.dir/MyProtoBuffTest_autogen/mocs_compilation.cpp.o
[ 30%] Building CXX object CMakeFiles/MyProtoBuffTest.dir/main.cpp.o
[ 40%] Linking CXX executable MyProtoBuffTest
[ 40%] Built target MyProtoBuffTest
[ 50%] Running cpp protocol buffer compiler on message.proto
[ 60%] Automatic MOC and UIC for target proto
[ 60%] Built target proto_autogen
[ 70%] Building CXX object proto/CMakeFiles/proto.dir/proto_autogen/mocs_compilation.cpp.o
[ 80%] Building CXX object proto/CMakeFiles/proto.dir/message.pb.cc.o
[ 90%] Linking CXX static library libproto.a
[100%] Built target proto
llist@poldis:~/QtProjects/MyProtoBuffTest/build$ 

That looks like it works to me…what isn’t working here? Your protobuf install is under /usr, so the variable value makes sense to me.

Sorry, I should have made this clearer.
I thought/expected the “Protobuf_INCLUDE_DIRS” to point to the location of the generated headers as my real issue is that these headers are not found (as in the output of the first post).

I think I found the reason for the make not finding the headers generated by protobuf_generate_cpp.
I’ve added another class to the proto folder and after the build I can include that header file without any issues.
The reason is/seems to be that the new class files are under the initial src folder, while the class generated by protobuf_generate_cpp ends up under the build folder.

Yes, code generation should write to the build tree rather than the source tree (so that multiple builds of the same source do not overlap).

Thanks.
So what variable should I set so the compiler finds the gernerated files?

You don’t set a variable, but instead pass the path (usually something based on CMAKE_CURRENT_BINARY_DIR) as an include path:

target_include_directories(with_protobuf_srcs PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/subdir")

There might not be a subdir. Ideally, generate_protobuf would given such information returned in a variable, but that looks like a feature request (to protobuf upstream itself) at the moment.

My two CMake files look like this

cmake_minimum_required(VERSION 3.14)

project(MyProtoBuffTest LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)

add_subdirectory(proto)

add_executable(MyProtoBuffTest
  main.cpp
#  test2.h test2.cpp
)
target_link_libraries(MyProtoBuffTest Qt${QT_VERSION_MAJOR}::Core)

include(GNUInstallDirs)
install(TARGETS MyProtoBuffTest
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY TARGET_INCLUDE_DIRECTORIES)
message("  This is where the root directories should be listed")
foreach(dir ${dirs})
  message(STATUS "root directory is ='${dir}'")
endforeach()
INCLUDE(FindProtobuf)
FIND_PACKAGE(Protobuf REQUIRED)
protobuf_generate_cpp(PROTO_SRC PROTO_HEADER message.proto)
ADD_LIBRARY(proto ${PROTO_HEADER} ${PROTO_SRC}
    test1.h test1.cpp
)
target_include_directories(proto PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/proto")

# target_include_directories(proto PUBLIC ${CMAKE_BINARY_DIR}/proto)

message("   --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}")
message("   --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}")
message("   --> PROTOBUF VERSION: ${Protobuf_VERSION}")
message("   --> PROTOBUF Found: ${Protobuf_FOUND}")
message("   --> PROTOBUF SRC: ${PROTO_SRC}")
message("   --> PROTOBUF HEADER: ${PROTO_HEADER}")
message("   --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto")

get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY TARGET_INCLUDE_DIRECTORIES)
message("  This is where the proto directories should be listed")
foreach(dir ${dirs})
  message(STATUS "proto directory is ='${dir}'")
endforeach()

Output form cmake and make is as follows

llist@poldis:~/QtProjects/MyProtoBuffTest/build$ cmake ..
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE  
-- Performing Test HAVE_STDATOMIC
-- Performing Test HAVE_STDATOMIC - Success
-- Found WrapAtomic: TRUE  
-- Found Protobuf: /usr/lib/x86_64-linux-gnu/libprotobuf.so (found version "3.12.4") 
   --> PROTOBUF LIB: /usr/lib/x86_64-linux-gnu/libprotobuf.so
   --> PROTOBUF INCLUDE: /usr/include
   --> PROTOBUF VERSION: 3.12.4
   --> PROTOBUF Found: TRUE
   --> PROTOBUF SRC: /home/llist/QtProjects/MyProtoBuffTest/build/proto/message.pb.cc
   --> PROTOBUF HEADER: /home/llist/QtProjects/MyProtoBuffTest/build/proto/message.pb.h
   --> PROTOBUF Folder: /home/llist/QtProjects/MyProtoBuffTest/build/proto
  This is where the proto directories should be listed
  This is where the root directories should be listed
-- Configuring done
-- Generating done
-- Build files have been written to: /home/llist/QtProjects/MyProtoBuffTest/build
llist@poldis:~/QtProjects/MyProtoBuffTest/build$ make
[  9%] Automatic MOC and UIC for target MyProtoBuffTest
[  9%] Built target MyProtoBuffTest_autogen
[ 18%] Building CXX object CMakeFiles/MyProtoBuffTest.dir/MyProtoBuffTest_autogen/mocs_compilation.cpp.o
[ 27%] Building CXX object CMakeFiles/MyProtoBuffTest.dir/main.cpp.o
/home/llist/QtProjects/MyProtoBuffTest/main.cpp:3:10: fatal error: proto/message.pb.h: No such file or directory
    3 | #include "proto/message.pb.h"
      |          ^~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/MyProtoBuffTest.dir/build.make:90: CMakeFiles/MyProtoBuffTest.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:102: CMakeFiles/MyProtoBuffTest.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

You need to target_include_directories(MyProtoBuffTest PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") to do this. It’d be better as part of the proto target’s INTERFACE, but that weirdly wants ${CMAKE_CURRENT_BINARY_DIRECTORY}/.. from its point of view.

I’ve added
target_include_directories(MyProtoBuffTest PRIVATE “${CMAKE_CURRENT_BINARY_DIR}”)
to the Root CMakeLists.txt; the error persists.

Thanks,
Leo

Is "${CMAKE_CURRENT_BINARY_DIR}" not this path in that context?

I now have

target_include_directories(MyProtoBuffTest PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")

in the root CMakeLists.txt and

target_include_directories(proto PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

in the subfolder that creates the files from the proto definition.

It now all works

Thanks for your help
Leo