Скомпилировать C++ файлы из proto-файлов с помощью CMake
Всем привет! Пишу на С++ grpc-клиент и хочу чтобы proto-файлов компилировались во время сборки проекта. Для этого подтягиваю исходники grpc из официального репозитория(https://github.com/grpc/grpc)
В интернете прочитал что нужно использовать функцию protobuf_generate_grpc_cpp(HEADERS SOURCES path_to_proto_files)
CMakeLists.txt вот-такой:
cmake_minimum_required(VERSION 3.5)
project(test_grpc LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(gRPC_BUILD_GRPC_RUBY_PLUGIN off)
set(gRPC_BUILD_GRPC_PYTHON_PLUGIN off)
set(gRPC_BUILD_GRPC_PHP_PLUGIN off)
set(gRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN off)
set(gRPC_BUILD_GRPC_NODE_PLUGIN off)
set(gRPC_BUILD_GRPC_CSHARP_PLUGIN off)
set(gRPC_INSTALL ON)
set(gRPC_BUILD_TESTS OFF)
add_subdirectory(grpc)
protobuf_generate_grpc_cpp(HEADERS SOURCES /home/ilyas/avanpost/avanpost-idp/protos)
message(STATUS ${HEADERS})
set(HDRS
agentcontrol.grpc.pb.h
wrappers.grpc.pb.h
timestamp.grpc.pb.h
agentcontrol.pb.h
wrappers.pb.h
timestamp.pb.h
)
set(SRCS
agentcontrol.grpc.pb.cc
wrappers.grpc.pb.cc
timestamp.grpc.pb.cc
agentcontrol.pb.cc
wrappers.pb.cc
timestamp.pb.cc
)
add_executable(test_grpc main.cpp ${HDRS} ${SRCS})
target_link_libraries(test_grpc grpc++)
message(STATUS ${HEADERS} ${SOURCES}) возвращает пустые строки.
Пробовал сделать как написано в этом вопросе. Но ничего не получилось и зачем тогда функция protobuf_generate_grpc_cpp(HEADERS SOURCES path_to_proto_files)?
Как мне сделать так что бы proto-файлы собирались во время сборки проекта и как можно указать место для собранных файлов?
Ответы (2 шт):
Функция protobuf_generate_grpc_cpp третим параметром получить список proto файлов, которые она будет обрабатывать. А Вы ей даете каталог. А она так не умеет. Либо давайте с именами
protobuf_generate_grpc_cpp(HEADERS SOURCES /home/ilyas/avanpost/avanpost-idp/protos/my.proto)
или пусть cmake Вам немного поможет
file(GLOB ProtoFiles " /home/ilyas/avanpost/avanpost-idp/protos/*.proto")
protobuf_generate_grpc_cpp(HEADERS SOURCES ${ProtoFiles})
И теперь HEADERS и SOURCES будут содержать список сгенерированных файлов, которые можно добавить в нужные бинарники.
Как мне сделать так что бы proto-файлы собирались во время сборки проекта вот так как написано выше. Есть еще десяток неверных способов, их не стоит делать.
как можно указать место для собранных файлов?
А вот этого Вам не должно хотеться. Файлы, которые нагенерировал протобаф - это такие же файлы, как и *.o или *.pdb. И они все лежат вместе. Я видел несколько случаев, когда пытались использовать "ручной способ" генерации и потом ругались на cmake, на протобаф, на все остальное кроме себя.
Но почему так? все дело в том, что в правильном варианте cmake отслеживает факт изменения прото файлов и корректно пересобирает все зависимости. Если же делать ручками, то либо протобаф всегда перегенерируется (а это увеличение времени компиляции и пересборка того, что не должно было бы пересобираться) либо наоборот - "я тут поменял, а оно не пересобрало!"
P.S. Мне очень не нравится полный путь к протобаф файлам. Там точно должен быть относительный.
Решил проблему так:
add_subdirectory(grpc)
find_program(PROTOC protoc)
find_program(GRPC_CPP_PLUGIN grpc_cpp_plugin)
get_filename_component(PROTOS_DIR "proto" ABSOLUTE)
file(GLOB PROTOS ${PROTOS_DIR}/*.proto)
set(GENS ${CMAKE_BINARY_DIR}/gens)
make_directory(${GENS})
execute_process(COMMAND ${PROTOC}
-I ${PROTOS_DIR}
--cpp_out=.
--grpc_out=.
--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}
${PROTOS}
WORKING_DIRECTORY ${GENS}
RESULT_VARIABLE res
OUTPUT_VARIABLE out
)
file(GLOB GRPC_PROTOC_GENS "${GENS}/*.cc" "${GENS}/*.h")
Но сначала необходимо собрать и установить grpc. Я это делаю из реппозитория на github.