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

如何在tonic_build中跨Crate导入公共common.proto文件?

解决方案

方法一:调整编译路径与导入语句

问题核心是protoc编译时的搜索路径和VSCode的路径逻辑不一致——你当前的build.rs只把players crate下的src/proto设为搜索目录,导致找不到工作区根目录下的common.proto。

1. 修改proto导入语句

将players.proto中的导入路径改为基于工作区根目录的相对路径:

syntax = "proto3";

package players;

import "google/protobuf/timestamp.proto";
// 改用基于工作区根目录的路径
import "common/src/common.proto";

2. 更新build.rs的搜索路径

在compile方法的第二个参数中,添加工作区根目录的相对路径(从players crate根目录到工作区根目录是../../../):

fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::configure()
        .out_dir("src/proto")
        .compile(
            &["src/proto/players.proto"],
            &["src/proto", "../../../"], // 加入工作区根目录作为protoc搜索路径
        )?;

    Ok(())
}

3. 同步VSCode识别路径(可选)

为了让VSCode的proto插件也能正确识别导入路径,在工作区的.vscode/settings.json中添加:

{
    "protoc.options": ["--proto_path=${workspaceFolder}"]
}

方法二:将common封装为独立依赖Crate(推荐)

重复在多个crate中管理proto导入容易出错,更优雅的方式是把common做成独立crate,编译自身proto后供其他crate依赖:

1. 配置common crate的build.rs

在src/common/build.rs中编写编译逻辑:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::configure()
        .out_dir("src/proto") // 生成的rust代码放在src/proto目录
        .compile(
            &["src/common.proto"],
            &["src"],
        )?;

    Ok(())
}

2. 声明common crate的依赖

在src/common/Cargo.toml中添加必要依赖:

[dependencies]
tonic = "0.9"
prost = "0.12"

[build-dependencies]
tonic-build = "0.9"

3. 其他crate依赖common

在players/Cargo.toml中添加common crate的依赖:

[dependencies]
common = { path = "../../common" }
tonic = "0.9"
prost = "0.12"

这样players crate中无需再处理common.proto的导入,直接通过rust模块引用:

use common::proto::Pagination;
use common::proto::Page;

这种方式避免了重复编译proto,也简化了跨crate的类型共享,更符合Cargo工作区的设计理念。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:45:31