Estou tentando criar um pequeno projeto de teste em C++ que usa protobuf e o sistema de compilação cmake.
Consegui fazer tudo funcionar com um único diretório e um único arquivo CMakeLists.txt
.
No entanto, esta não é uma estrutura escalável.
A próxima mudança que tentei foi criar um proto
diretório e mover os *.proto
arquivos para ele.
O projeto não compila mais e não consigo descobrir como consertá-lo.
Pesquisei soluções na web e também tentei perguntar ao ChatGPT. O ChatGPT andou em círculos e encontrei o que pareciam ser soluções muito variáveis ao pesquisar os recursos limitados que pude encontrar online. Não era óbvio para mim qual das muitas variações poderia ser o caminho certo a seguir, mas isso é mais provável porque não sou especialista em cmake
, então não consegui descobrir como juntar as várias peças.
Isto é o que eu tenho atualmente:
protobuf-example/
proto/
CMakeLists.txt
message.proto
CMakeLists.txt
main.cpp
proto/CMakeLists.txt
Não tenho certeza do que abaixo é necessário. Tenho algum entendimento do que cada uma dessas linhas faz, mas meu entendimento não é muito sólido.
set(PROTO_FILES message.proto)
set(GENERATED_PROTO_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated)
file(MAKE_DIRECTORY ${GENERATED_PROTO_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${PROTO_FILES})
add_library(proto_files STATIC ${PROTO_SRCS})
target_include_directories(proto_files PUBLIC ${Protobuf_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(proto_files PUBLIC ${Protobuf_LIBRARIES})
set(PROTO_GEN_SRCS ${PROTO_SRCS} PARENT_SCOPE)
set(PROTO_GEN_HDRS ${PROTO_HDRS} PARENT_SCOPE)
set(PROTO_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
message.proto
syntax = "proto3";
message Person {
string name = 1;
int32 age = 2;
string email = 3;
}
CMakeLists.txt
Por outro lado, estou familiarizado com essas afirmações e tenho quase certeza de que sei o que cada uma delas faz.
cmake_minimum_required(VERSION 3.10)
project(ProtobufExample LANGUAGES CXX)
find_package(Protobuf REQUIRED)
add_subdirectory(proto)
add_executable(protobuf_example main.cpp ${PROTO_GEN_SRCS})
target_include_directories(protobuf_example PRIVATE ${Protobuf_INCLUDE_DIR})
target_link_libraries(protobuf_example PRIVATE ${proto_files})
main.cpp
Até onde sei, este é apenas um exemplo padrão.
#include <iostream>
#include <fstream>
#include "message.pb.h"
void serializePerson(const std::string& filename) {
Person person;
person.set_name("John Doe");
person.set_age(30);
person.set_email("[email protected]");
std::ofstream output(filename, std::ios::binary);
if (!person.SerializeToOstream(&output)) {
std::cerr << "Failed to serialize data." << std::endl;
}
}
void deserializePerson(const std::string& filename) {
Person person;
std::ifstream input(filename, std::ios::binary);
if (!person.ParseFromIstream(&input)) {
std::cerr << "Failed to parse data." << std::endl;
} else {
std::cout << "Name: " << person.name() << "\n"
<< "Age: " << person.age() << "\n"
<< "Email: " << person.email() << std::endl;
}
}
int main() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
const std::string filename = "person.data";
serializePerson(filename);
deserializePerson(filename);
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
Erro
A mensagem de erro específica é:
Cannot find source file:
/home/user/cmake-protobuf-test/protobuf-example/build/proto/message.pb.cc
Provavelmente isso ocorre porque o build/proto/generated
diretório está vazio.
Então parece que o protobuf_generate_cpp
não está fazendo nada. No entanto, não há erros ou avisos produzidos relacionados a isso.
Há duas questões aí. A primeira:
deve ser
porque
${PROTO_GEN_SRCS}
são fontes deproto_files
.E o erro de digitação:
deve ser
porque alvos não são variáveis.
Uma crítica. Isso é desnecessário
porque o mais
target_link_libraries
traz #include paraprotobuf_example
.Isso resulta em que isso também é desnecessário