You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复拆分Proto目录后的CMake+Protobuf项目构建失败问题

Protobuf + CMake多目录构建失败问题解决

问题描述

将Protobuf文件移至单独的proto目录后,CMake构建失败,提示找不到生成的message.pb.cc文件,且build/proto/generated目录为空,protobuf_generate_cpp未生成文件但无任何错误或警告。

项目结构

protobuf-example/
  proto/
    CMakeLists.txt
    message.proto
  CMakeLists.txt
  main.cpp

各文件原始内容

proto/CMakeLists.txt

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

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

#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("john.doe@example.com");

    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;
}

错误信息

Cannot find source file:

    /home/user/cmake-protobuf-test/protobuf-example/build/proto/message.pb.cc

问题根源

  1. protobuf_generate_cpp 默认将文件生成到当前CMakeLists.txt的二进制根目录,但代码中指定了GENERATED_PROTO_DIR却未告知函数使用该目录,导致生成路径与预期不符。
  2. 主CMakeLists.txt中重复添加了${PROTO_GEN_SRCS},而源文件已通过proto_files库管理,重复添加会导致CMake寻找不存在的路径文件。
  3. 主CMakeLists中target_include_directories使用了错误的变量名${Protobuf_INCLUDE_DIR},正确应为${Protobuf_INCLUDE_DIRS}。

修正方案

1. 更新proto/CMakeLists.txt

调整protobuf_generate_cpp调用,明确指定输出目录,同时移除不必要的父作用域变量传递:

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
    OUT_DIR ${GENERATED_PROTO_DIR}
    ${PROTO_FILES}
)

add_library(proto_files STATIC ${PROTO_SRCS})

# 让依赖库的目标能访问到生成的头文件和Protobuf头文件
target_include_directories(proto_files PUBLIC
    ${Protobuf_INCLUDE_DIRS}
    ${GENERATED_PROTO_DIR}
)

target_link_libraries(proto_files PUBLIC ${Protobuf_LIBRARIES})

2. 更新主CMakeLists.txt

移除重复的源文件引用,修正变量名,简化依赖配置:

cmake_minimum_required(VERSION 3.10)
project(ProtobufExample LANGUAGES CXX)

find_package(Protobuf REQUIRED)

add_subdirectory(proto)

# 无需添加${PROTO_GEN_SRCS},源文件已包含在proto_files库中
add_executable(protobuf_example main.cpp)

# 无需单独配置include目录,proto_files已通过PUBLIC暴露必要路径
target_link_libraries(protobuf_example PRIVATE proto_files)

3. 重新构建

清理旧构建目录后重新执行:

rm -rf build && mkdir build && cd build
cmake ..
make

此时message.pb.cc和message.pb.h会正确生成到build/proto/generated目录,项目可正常编译运行。

内容的提问来源于stack exchange,提问作者user2138149

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:54:50