Issue
In the following project structure:
root/
├─ CMakeLists.txt
├─ protocol/
│ ├─ msg.proto
│ ├─ CMakeLists.txt
├─ app/
│ ├─ main.cpp
│ ├─ CMakeLists.txt
I could generate the protobuf files. However, once the app
target is added into the project, the configuration step fails, because the protobuf files are not generated anymore.
root CMakeLists.txt:
cmake_minimum_required(VERSION 3.18.4)
project(
root
VERSION 0.1
LANGUAGES CXX
)
add_subdirectory(protocol)
add_subdirectory(app)
protocol CMakeLists.txt:
add_library(protocol)
target_include_directories(protocol
PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${Protobuf_INCLUDE_DIRS}
)
find_package(Protobuf REQUIRED)
set(PROTO_SOURCES msg.proto)
protobuf_generate_cpp(LIB_SOURCES LIB_HEADERS ${PROTO_SOURCES} )
target_link_libraries(protocol ${Protobuf_LIBRARIES})
target_sources(protocol
PUBLIC
${LIB_HEADERS}
PRIVATE
${LIB_SOURCES}
)
app CMakeLists.txt:
add_library(app)
target_link_libraries(app PUBLIC protocol)
target_include_directories(app PUBLIC .)
target_sources(app
PRIVATE
main.cpp
)
The way I understand it is that somehow I have to tell CMAKE the dependency, but as far as I know target_link_libraries
should tell exactly that.
Another step I could take is to tell the app
target that the headers in the protocol
library are generated at build, so they can be generated before the dependant target compiles. How can it be done?
Many other questions reference similar problems, but none that I found had library dependencies in mind.
Update:
After moving ${LIB_HEADERS}
from PUBLIC
to PRIVATE
:
add_library(protocol)
target_include_directories(protocol
PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${Protobuf_INCLUDE_DIRS}
)
find_package(Protobuf REQUIRED)
set(PROTO_SOURCES msg.proto)
protobuf_generate_cpp(LIB_SOURCES LIB_HEADERS ${PROTO_SOURCES} )
target_link_libraries(protocol ${Protobuf_LIBRARIES})
target_sources(protocol
PRIVATE
${LIB_HEADERS}
${LIB_SOURCES}
)
the configure step is successful, the msg.pb.h files are generated into the protocol
subfloder in build
; but make fails with the following error:
main.cpp:29:10: fatal error: protocol/msg.pb.h: No such file or directory
29 | #include "protocol/msg.pb.h"
|
So how can the headers be provided from target protocol
in this setup?
Solution
Based on help from @Tsyvarev:
After moving ${LIB_HEADERS}
from PUBLIC
to PRIVATE
, the protobuf files are now generated.
To make them reachable through the library for the include
#include "protocol/msg.pb.h"
${CMAKE_BINARY_DIR}
Needs to be changed into ${CMAKE_CURRENT_BINARY_DIR}
in target_include_directories
.
In case I the code uncludes protobuf headers directly:
#include "msg.pb.h"
${CMAKE_CURRENT_BINARY_DIR}
needs to be there.
Because:
${CMAKE_CURRENT_BINARY_DIR}
represents the submodule binary directoy (protocol
project${CMAKE_CURRENT_BINARY_DIR}
represents the project binary directoy (protocol
project
Answered By - David Tóth