[cmake-developers] [CMake 0016077]: FindProtobuf.cmake doesn't have required flexibility to configure protoc usage for all use cases

Mantis Bug Tracker mantis at public.kitware.com
Fri Apr 22 17:09:01 EDT 2016


The following issue has been SUBMITTED. 
====================================================================== 
https://cmake.org/Bug/view.php?id=16077 
====================================================================== 
Reported By:                skebanga
Assigned To:                
====================================================================== 
Project:                    CMake
Issue ID:                   16077
Category:                   Modules
Reproducibility:            always
Severity:                   minor
Priority:                   normal
Status:                     new
====================================================================== 
Date Submitted:             2016-04-22 17:09 EDT
Last Modified:              2016-04-22 17:09 EDT
====================================================================== 
Summary:                    FindProtobuf.cmake doesn't have required flexibility
to configure protoc usage for all use cases
Description: 
I have here a very simple test project which has 2 protobuf files, one of which
is included in the other.

Using cmake, I will create a static library for each generated protobuf message.

##Protobuf files:

**`src/foo/message.proto`:**

    package test.foo;
    
    message FooMsg
    {
        required string s = 1;
    }

**`src/bar/message.proto`:**

    package test.bar;
    import "foo/message.proto";
    
    message BarMsg
    {
        optional foo.FooMsg f = 1;
    }

##CMake files:

I build `lib_foo` from generated `foo/message.proto` files.

**`src/foo/CMakeLists.txt`:**

    protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS message.proto)
    
    add_library(lib_foo STATIC ${PROTO_SRCS})

I build `lib_bar` from the generated `bar/message.proto` files, and link in
`lib_foo`:

**`src/bar/CMakeLists.txt`:**

    protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS message.proto )
    
    add_library(lib_bar STATIC ${PROTO_SRCS})
    
    target_link_libraries(lib_bar lib_foo)

**`src/CMakeLists.txt`:**

    cmake_minimum_required (VERSION 3.5)
    project (cmake_proto_test CXX)
    
    find_package(Protobuf REQUIRED)
    
    # proto files import from the source root directory, so add the required -I
flag
    set(PROTOBUF_IMPORT_DIRS ${CMAKE_SOURCE_DIR})
    
    # genererated proto files go into the CMake binary output dir
    include_directories("${CMAKE_BINARY_DIR}")
    
    add_subdirectory(foo)
    add_subdirectory(bar)

##Build error:

When I try to build this, I get the following error:

    $ make .. VERBOSE=1
    cd src/cmake_proto/build/bar && /usr/bin/c++    
        -I src/cmake_proto/build   
        -o CMakeFiles/lib_bar.dir/message.pb.cc.o 
        -c src/cmake_proto/build/bar/message.pb.cc

    In file included from src/cmake_proto/build/bar/message.pb.cc:5:0:

    src/cmake_proto/build/bar/message.pb.h:99:24: 
        error: ‘foo’ in namespace ‘test’ does not name a type

           inline const ::test::foo::FooMsg& f() const;
                                ^

##Reason:

The error is due to the header guard created by `protoc` being the same for the
2 generated files:

    #ifndef PROTOBUF_message_2eproto__INCLUDED
    #define PROTOBUF_message_2eproto__INCLUDED

    ...

    #endif

The reason is that the header guard is derived from a combination of the output
directory and the generated file's path.

The current command issued by `FindProtobuf.cmake` results in the header guard
only using the filename:

    cd src/cmake_proto/build/foo && /usr/local/bin/protoc --cpp_out
src/cmake_proto/build/foo -I src/cmake_proto/foo -I src/cmake_proto
src/cmake_proto/foo/message.proto
    cd src/cmake_proto/build/bar && /usr/local/bin/protoc --cpp_out
src/cmake_proto/build/bar -I src/cmake_proto/bar -I src/cmake_proto
src/cmake_proto/bar/message.proto

This command, however, will result in the files being generated in the same
location, but with a different header guard:

    cd src/cmake_proto/build && /usr/local/bin/protoc --cpp_out
src/cmake_proto/build -I src/cmake_proto src/cmake_proto/foo/message.proto
    cd src/cmake_proto/build && /usr/local/bin/protoc --cpp_out
src/cmake_proto/build -I src/cmake_proto src/cmake_proto/bar/message.proto

Header guards:

    PROTOBUF_foo_2fmessage_2eproto__INCLUDED
    PROTOBUF_bar_2fmessage_2eproto__INCLUDED

There are three key differences here:

- The `WORKING_DIRECTORY` from which `protoc` is run from is
`${CMAKE_BINARY_DIR}`
- The `--cpp_out` directory passed to `protoc` is `${CMAKE_BINARY_DIR}`
- The `-I` include path passed to `protoc` does **not** include the folder where
the proto file is found

Being able to control these 3 items would give the flexibility required to use
this tool in the above setup.


====================================================================== 

Issue History 
Date Modified    Username       Field                    Change               
====================================================================== 
2016-04-22 17:09 skebanga       New Issue                                    
======================================================================



More information about the cmake-developers mailing list