2017-01-02 2 views
0

Я видел много подобных вопросов и ответов, но до сих пор кажется не столь очевидным, чтобы заставить его работать. Я совершенно новый для CMake, и до сих пор все было легко, кроме интеграции с буферами протоколов.CMake с файлом protobuf в подкаталоге

У меня есть проект с подкаталогами, где каждый подкаталог имеет свой собственный CMakeLists.txt

Один из поддиректории содержит файл .proto. Если выполняется макрос PROTOBUF_GENERATE_CPP, он генерирует источники и файлы заголовков. Этот макрос вызывается из CMakeLists.txt в подкаталоге, содержащем файл .proto.

Кажется, что файл make не вызывается, потому что никакие источники не добавляются к цели. Я не могу добавить источники в цель, потому что файлы не существуют, они существуют после генерации, поэтому это приводит к ошибке при запуске CMake.

Настройка свойств файла, сгенерированных, также не помогает. В общем, перед запуском процесса сборки макрос должен быть запущен для создания исходных файлов.

Как это сделать, любые рабочие примеры?

Пример:

./src/externals/protodef (из другого хранилища, содержит только .proto файлы)
./src/generated (предполагается для сгенерированного С и заголовочных файлов по protoc)

CMakeLists-1 (корень проекта)

cmake_minimum_required (VERSION 2.6) 
PROJECT (prototest) 

ADD_SUBDIRECTORY("${PROJECT_SOURCE_DIR}/src/externals/protodef") 
ADD_SUBDIRECTORY("${PROJECT_SOURCE_DIR}/src") 

SET_SOURCE_FILES_PROPERTIES(${PROTO_SOURCES} ${PROTO_HEADERS} PROPERTIES GENERATED TRUE) 

ADD_EXECUTABLE(prototest ${PROTO_SOURCES} ${SOURCE}) 
TARGET_LINK_LIBRARIES(prototest ${EXTERNAL_LIBS}) 

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 

CMakeLists-2 (SRC)

SET(SOURCE ${SOURCE} 
    ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 

    PARENT_SCOPE 
) 

CMakeLists-3 (SRC/внешние/protodef)

SET(PROTOBUF_PATH "D:/protobuf-3.0.0/") 
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${PROTOBUF_PATH}") 

# Changing PROTO_SRCS and PROTO_HDRS does not work for setting the location 
# of the generated files. 
# Those variable are ignored by CMake for compiling the proto files. 
# Using a dedicated CMakeLists.txt and settng CURRENT_BINARY dir is a 
# workaround to get them where we want. 
SET(GENERATED_DIR ${PROJECT_SOURCE_DIR}/src/generated) 
SET(CMAKE_CURRENT_BINARY_DIR ${GENERATED_DIR}) 


INCLUDE(FindProtobuf) 
FIND_PACKAGE(Protobuf REQUIRED) 

PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS${CMAKE_CURRENT_SOURCE_DIR}/test1.proto) 

SET(EXTERNAL_LIBS ${PROTOBUF_PATH}/lib/libprotobuf.a PARENT_SCOPE) 

# Propagate sources to the parant project 
SET(PROTO_SOURCES ${PROTO_SRCS} 
PARENT_SCOPE 
) 

SET(PROTO_HEADERS ${PROTO_HDRS} 
PARENT_SCOPE 
) 
+0

пожалуйста оставить [mcve] –

+0

вы должны пометить сгенерированные файлы .h и .cpp с свойством GENERATED, так что cmake знает, что они будут существовать, когда придет время их создания. –

+0

@Richard Я попытался установить свойство GENERATED.Кажется, что единственное, что он делает, это заполнение имен файлов «сгенерированных» файлов в переменные, переданные макросу. Но в этом случае файлы все еще не существуют и добавление переменной в файлы исходных файлов проекта приводит к ошибке cmake, поскольку она содержит имя несуществующего файла. – Waldorf

ответ

0

сгенерировать файлы Protobuf, а затем добавить их к цели CMake.

CMakeLists (ЦСИ):

# Generate h/cpp proto files (./src/externals/protodef) into ./src/generated folder 
PROTOBUF_GENERATE_CPP(...) 

# Process subdir 
ADD_SUBDIRECTORY(generated) 

кажется, что PROTOBUF_GENERATE_CPP может быть использован только в том же подкаталоге. Возможным решением является вызвать protoc непосредственно вместо:

FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/externals/protodef PROTOMODEL_PATH) 
FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/generated PROTOBINDING_PATH) 

FILE(GLOB DATAMODEL_PROTOS "${CMAKE_CURRENT_SOURCE_DIR}/externals/protodef/*.proto") 

FOREACH(proto ${DATAMODEL_PROTOS}) 
    FILE(TO_NATIVE_PATH ${proto} proto_native) 
    EXECUTE_PROCESS(COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --proto_path=${PROTOMODEL_PATH} --cpp_out=${PROTOBINDING_PATH} ${proto_native} 
    RESULT_VARIABLE rv) 
    # Optional, but that can show the user if something have gone wrong with the proto generation 
    IF(${rv}) 
     MESSAGE("Generation of data model returned ${rv} for proto ${proto_native}") 
    ENDIF() 
ENDFOREACH(proto) 

CMakeLists (ЦСИ/генерироваться):

## List generated sources files 
FILE(GLOB HDRS "*.h") 
FILE(GLOB SRCS "*.cc") 

ADD_LIBRARY(protoBinding ${HDRS} ${SRCS}) 
# ${PROTOBUF_LIBRARIES} should be defined by FIND_PACKAGE(Protobuf REQUIRED) 
TARGET_LINK_LIBRARIES(protoBinding ${PROTOBUF_LIBRARIES}) 

Таким образом CMake будет первым генерировать заголовок/исходные файлы, и только затем добавить сгенерированные файлы к цели CMake.

Вы можете использовать protoBinding цель связать сгенерированные файлы на другой цели (например, в конце CMakeLists.txt src «s):

ADD_LIBRARY(myModel ${myFiles}) 
TARGET_LINK_LIBRARIES(myModel protoBinding) 
+0

Я использовал второй вариант, который дает немного больше контроля. Отлично работает. В моем случае PROTOBUF_LIBRARIES указывает на libprotobuf.dll.a Я хочу связать libprotobuf статически, как советует Google. В настоящее время я устанавливаю lib вручную, возможно, есть более чистый способ. – Waldorf

Смежные вопросы