Подтвердить что ты не робот

CMake и FindProtobuf

Я использую модуль FindProtobuf в проекте, где файлы буфера протокола находятся в подкаталоге. Я хочу, чтобы файл CMakeLists.txt в этом подкаталоге вызывал protoc для создания файлов CPP. Структура моего проекта такова:

cammy/CMakeLists.txt   # Root CMakeLists.txt
cammy/protofiles/test.proto # protofile
cammy/protofiles/CMakeLists.txt

У меня есть include (FindProtobuf), вызов find_package и вызов PROTOBUF_GENERATE_CPP в файле CMakeLists.txt в папке protobuf.

Выполняемый шаг сборки находится в файле Root CMakeLists.txt, и я добавляю сгенерированные файлы к целевому исполняемому файлу в этом файле то есть.

add_executable( ${EXEC} ${SRCS} ${PROTO_SRC} ${PROTO_HEADER} )
target_link_libraries( ${EXEC} ${PROTOBUF_LIBRARIES} )

оба определены в корне CMakeLists.txt

Когда я запускаю cmake, он не запускает protoc для генерации исходных файлов, даже если я окончательно привязываю сгенерированные источники к исполняемому файлу, тем самым создавая зависимость.

Когда я перемещаю все содержимое CMakeLists.txt в папке protofiles в корневой файл CMakeLists.txt, файлы proto скомпилируются.

Может ли кто-нибудь помочь мне с этим? Я хочу, чтобы все материалы для создания буфера протокола вошли в файл CMakeLists.txt, созданный в папке прототипов.

Я также заметил, что переменные, созданные во внутреннем файле CMakeLists.txt(например, PROTO_SRC), определены во внутреннем файле при печати (т.е. я получаю правильное имя файла CPP), но когда я печатаю одну и ту же переменную в корневом файле. он пуст. Его почти как будто мне нужно "экспортировать" (если был способ в cmake), переменные попадают в корневую папку.

Любая помощь будет высоко оценена.

Спасибо Картик

4b9b3361

Ответ 1

Я думаю, FindProtobuf на самом деле не предназначена для использования сюда. Из своих документов:

ПРИМЕЧАНИЕ. Макрос PROTOBUF_GENERATE_CPP и add_executable() или add_library()       звонки работают только в одном каталоге.

Вы пытаетесь использовать макрос PROTOBUF_GENERATE_CPP в подкаталоге, и хотя документы CMake действительно не дают ясности, подкаталог вводит новую область переменных. Это означает, что любые переменные, установленные или измененные в области subdir, не влияют на аналогично названные переменные в родительской области. Следовательно, причина для PROTO_SRC доступна в вашем прототипе dir, но не в родительском.

Способ передачи переменных в область видимости заключается в использовании set(... PARENT_SCOPE), поэтому в protofiles/CMakeLists.txt вы можете сделать:

PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER test.proto)

set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE)
set(PROTOBUF_LIBRARIES ${PROTOBUF_LIBRARIES} PARENT_SCOPE)
set(PROTO_SRC ${PROTO_SRC} PARENT_SCOPE)
set(PROTO_HEADER ${PROTO_HEADER} PARENT_SCOPE)

Однако это все равно не доходит до нас!

CMake фактически не вызывает компилятор protoc для генерации файлов .pb.h и .pb.cc - он использует add_custom_command для этого. Пользовательская команда указывает файлы .pb.h и .pb.cc как выходы, и настраиваемая команда вызывается (т.е. Protoc выполняется), если построена последующая цель, которая зависит от этих файлов.

Итак, во время настройки (когда выполняется CMake) эти файлы не существуют. Это проблема, если вы попытаетесь добавить их в качестве источников в команду add_library или add_executable - CMake необходимо сообщить, что эти файлы не существуют при ее запуске, но они будут существовать во время сборки.

Чтобы сделать это, установите > GENERATED для TRUE для этих файлов. Макрос PROTOBUF_GENERATE_CPP делает это автоматически, но, как и в случае с переменными, свойство не заполняется в родительскую область. Итак, в вашем CMakeLists.txt на верхнем уровне вам также нужно добавить:

set_source_files_properties(${PROTO_SRC} ${PROTO_HEADER} PROPERTIES
                            GENERATED TRUE)

Как вы можете видеть, использование PROTOBUF_GENERATE_CPP в другом каталоге для соответствующих команд add_library/add_executable немного хрупко. Если вы можете избежать этого, вы, вероятно, должны.