CMake with Google Protocol Buffers

36,299

I think the problem here is that the PROTOBUF_GENERATE_CPP function sets up the .pb.h and .pb.cc files to exist in the build tree, not in the source tree.

This is good practice (not polluting the source tree), but it means that your call include_directories(../messages) is adding the wrong value to the search paths. This is adding the source directory "root/messages", whereas you want "[build root]/messages".

You could probably just replace that line with:

include_directories(${CMAKE_BINARY_DIR}/messages)

However, a more robust, maintainable way might be to set the required include path inside the messages/CMakeLists.txt. To expose this value to the parent scope, this would need to either use set(... PARENT_SCOPE) or:

set(ProtobufIncludePath ${CMAKE_CURRENT_BINARY_DIR}
    CACHE INTERNAL "Path to generated protobuf files.")

Then in the top-level CMakeLists.txt, you can do:

include_directories(${ProtobufIncludePath})

If your messages library itself needs to #include the generated protobuf files (this would be normal), then it too should have a similar include_directories call.

Having said all that, if you can specify CMake v2.8.12 as the minimum, you can use the target_include_directories command instead.

In messages/CMakeLists.txt after the add_library call, you'd simply do:

target_include_directories(messages PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

Then any other target which depends on messages automatically has the appropriate "messages" include dirs added to its own - you don't need to explicitly call include_directories at all.

Share:
36,299

Related videos on Youtube

dutt
Author by

dutt

Updated on December 30, 2020

Comments

  • dutt
    dutt over 3 years

    I'm trying to use cmake to build my little project using protocol buffers.

    There's a root directory with a number of subdirectories with a number of libraries and executables. My first thought was to have my .proto-files in a subdirectory, but when I read this answer I made a library out of it instead. But when I try to include a messages header in my executable it can't find it.

    Error message:

    fatal error: msgs.pb.h: No such file or directory
     #include "msgs.pb.h"
                         ^
    compilation terminated.
    

    I'm running it by creating a dir "build" and then "cmake .. && make" from inside it. I've looked and it seems the generated files get put in build/messages, so I could do include_directories(build/messages) but that doesn't seem...proper. Is there a proper way of doing this with protobuf? The reason I want the messages file in their own folder is they they'll be used in a lot of different small executables.

    Any other general tips for improvements to my CMake-structure is also appreciated :)

    Directories:

    root
       messages
       core
       server
    

    root/CMakeLists.txt:

    project(lillebror)
    cmake_minimum_required(VERSION 2.8)
    cmake_policy(SET CMP0015 NEW)
    
    set(Boost_USE_STATIC_LIBS ON)
    set(Boost_USE_MULTITHREADED ON)
    set(Boost_USE_STATIC_RUNTIME OFF)
    find_package(Boost COMPONENTS date_time log thread system)
    find_package(Protobuf REQUIRED)
    if(Boost_FOUND)
        add_definitions(-std=c++11)
        add_subdirectory(messages)
        add_subdirectory(core)
        add_subdirectory(server)
        add_subdirectory(testserver)
    endif()
    

    messages/CMakeLists.txt:

    file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
    PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles})
    add_library(messages STATIC ${ProtoSources} ${ProtoHeaders})
    target_link_libraries(messages ${Boost_LIBRARIES} ${PROTOBUF_LIBRARY})
    

    core/CMakeLists.txt:

    aux_source_directory(src SRC_LIST)
    add_library(core STATIC ${SRC_LIST})
    target_link_libraries(core messages ${Boost_LIBRARIES})
    

    server/CMakeLists.txt:

    aux_source_directory(src SRC_LIST)
    include_directories(../messages) <---- I thought this would sove my problem
    include_directories(../core/src)
    link_directories(../core/build)
    add_executable(server ${SRC_LIST})
    target_link_libraries(server core ${Boost_LIBRARIES})
    

    server/main.cpp:

    #include "msgs.pb.h"
    int main()
    {
        return 0;
    }
    
  • dutt
    dutt over 10 years
    it seems ubuntu stable is running 2.8.11 so I went with the slightly longer version.
  • Fraser
    Fraser over 10 years
    I should have also mentioned: there should be no need for the link_directories call (it's own documentation discourages its use), and as you probably know, the add_definitions(-std=c++11) should probably only be applied if the compiler is GCC or Clang I guess. Apart from that, the structure all looks fine to me.
  • dutt
    dutt over 10 years
    Ah, I'll try to remove the link_directories call then. I'm using gcc for this little project so that definition is fine, but thanks for mentioning it anyway :)