CMake使用Protobuf的正确姿势
工程上有一个非常基础的原则,就是: 关联度越高的逻辑应该越靠近 。 但实践中,往往容易忽视,导致的结果就是:出了问题,我们要从一个非常遥远的错误,慢慢回溯,找到最根本的原因。
近来研究如何在cmake中使用Protobuf, 官方提供了一个示例,如下:
(引自:https://cmake.org/cmake/help/latest/module/FindProtobuf.html#example-processing-proto-schema-files)
cmake_minimum_required(VERSION 3.24)
project(ProtobufExample)
add_executable(example main.cxx person.proto)
find_package(Protobuf)
if(Protobuf_FOUND)
protobuf_generate(TARGET example)
endif()
target_link_libraries(example PRIVATE protobuf::libprotobuf)
target_include_directories(example PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
运行之后报错:
[0/1] Re-running CMake...
-- Protobuf_FOUND TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /data/research/v_demo/demos/ProtobufDemo/build
ninja: error: 'protobuf::protoc', needed by 'person.pb.cc', missing and no known rule to make it
这个错误的原因是编译机上没有proto-compiler,导致cc文件没有生成,但这个错误日志其实没有明确指向这个原因。
但从CMakeCache.txt容易发现问题:
Protobuf_PROTOC_EXECUTABLE:FILEPATH=Protobuf_PROTOC_EXECUTABLE-NOTFOUND
因此,apt install protobuf-compiler之后就能正常构建了。
实际上,如果官方Demo像下面这样,会更合理:
cmake_minimum_required(VERSION 3.24)
project(ProtobufExample)
add_executable(example main.cxx person.proto)
find_package(Protobuf)
message(STATUS "Protobuf_FOUND ${Protobuf_FOUND}")
if (Protobuf_PROTOC_EXECUTABLE)
#pass
else()
message(FATAL_ERROR "Protobuf_PROTOC_EXECUTABLE not found")
endif()
if(Protobuf_FOUND)
protobuf_generate(TARGET example)
else()
message(FATAL_ERROR "Protobuf not found")
endif()
target_link_libraries(example PRIVATE protobuf::libprotobuf)
target_include_directories(example PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
如果一个错误无法挽回,应该在距离错误最近的地方告知。
实际上,大部分Bug的排查过程,就是寻找这个最近地方的过程。