Ethan T
Ethan T

Reputation: 1490

How do I properly import, into a parent CMake project, a Protobuf-generated .h file created in a dependency CMake project?

Here is what my project hierarchy looks like (simplified):

+-- CMakeLists.txt
+-- party
|   +-- CMakeLists.txt
|   +-- include
|   \-- src
|       \-- party.cc
\-- super
    +-- CMakeLists.txt
    +-- include
    |   \-- super.h
    \-- src
        +-- super.cc
        \-- super.proto

I have a library CMake project, called Super, that has some Google Protobuf code in it. A source file, super.proto, is used by the protoc compiler to create super.pb.cc and super.pb.h. Super's CMakeLists.txt looks like this:

cmake_minimum_required(VERSION 3.1)
project(Super)
find_package(Protobuf REQUIRED)

set(INCLUDE_DIR "include")
set(SRC_DIR "src")

add_definitions("-std=c++11")

include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${INCLUDE_DIR})
include_directories(${PROTOBUF_INCLUDE_DIRS})

# === Super library ===
PROTOBUF_GENERATE_CPP(super_proto_srcs super_proto_incl ${SRC_DIR}/super.proto)
file(GLOB shared_srcs "${SRC_DIR}/*.cc")
add_library(super SHARED ${shared_srcs} ${super_proto_srcs})
target_link_libraries(super ${PROTOBUF_LIBRARIES})

# === Install and exports ===
set(${PROJECT_NAME}_INCLUDE_DIRS
    ${PROJECT_SOURCE_DIR}/include
    CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)

Super is to become a shared library named libsuper.so. It has a header file that depends on super.pb.h.

Party is a binary that uses libsuper.so. It doesn't care about Protobuf, at least not directly. It includes super.h and calls its method. Party has a CMakeLists.txt that looks like this:

cmake_minimum_required(VERSION 3.1)
project(Party)

set(INCLUDE_DIR "include")
set(SRC_DIR "src")

add_definitions("-std=c++11")

include_directories(${INCLUDE_DIR})
include_directories(${Super_INCLUDE_DIRS})

# === Party binary ===
file(GLOB binary_srcs "${SRC_DIR}/*.cc")
add_executable(party ${binary_srcs})
target_link_libraries(party super)

At the level of the parent directory, the unifying CMakeLists.txt looks like this:

cmake_minimum_required(VERSION 3.1)
project(SuperParty)

add_subdirectory(super)
add_subdirectory(party)

I can build Super on its own with no errors. The Protobuf-generated files are created, also libsuper.so. However, when I try to build the master project, SuperParty, I get the following error:

In file included from superparty/party/src/party.cc:1:0:
superparty/super/include/super.h:1:22: fatal error: super.pb.h: No such file or directory

The file exists in SuperParty's build/ directory, called build/super/super.pb.h. My problem is that I need to tell Party to include this auto-generated file, but I don't know where to get that file's path so that I can create the appropriate line in Party's CMakeLists.txt. Party effectively needs a reference to the CMAKE_BINARY_PATH that the master project is using.

Upvotes: 1

Views: 921

Answers (1)

Ethan T
Ethan T

Reputation: 1490

Turns out there's an automatic variable created named Super_BINARY_DIR that I could use in Party's CMakeLists.txt, but there is, in fact, an even better way to do it. Instead of modifying Party, which was already getting its list of includes from Super_INCLUDE_DIRS, I added a CMAKE_CURRENT_BINARY_DIR to the list of includes that Super created for Party to use. Here is the new ending to Super's CMakeLists.txt:

# === Install and exports ===
set(${PROJECT_NAME}_INCLUDE_DIRS
    ${CMAKE_CURRENT_BINARY_DIR}
    ${PROJECT_SOURCE_DIR}/include
    CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)

Upvotes: 1

Related Questions