CMake使用Protobuf的正确姿势

本文约 600 字,阅读需 2 分钟。

工程上有一个非常基础的原则,就是: 关联度越高的逻辑应该越靠近 。 但实践中,往往容易忽视,导致的结果就是:出了问题,我们要从一个非常遥远的错误,慢慢回溯,找到最根本的原因。

近来研究如何在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的排查过程,就是寻找这个最近地方的过程。

总阅读量次。