首页
/ Kong crate_locks 详解:Bazel + rules_rust 下 Rust 依赖锁文件的作用与 Repin 操作流程

Kong crate_locks 详解:Bazel + rules_rust 下 Rust 依赖锁文件的作用与 Repin 操作流程

2026-09-05 09:46:23作者:尤辰城Agatha

本文基于 Kong 仓库中的 crate_locks/README.md 及其配套源码,讲解 Kong 在 Bazel 构建体系中如何管理 Rust 依赖(atc-router)的锁文件:xxx.Cargo.lockxxx.lock 各自由谁生成、各自承担什么职责,以及如何使用 CARGO_BAZEL_REPIN 系列环境变量对指定 crate 索引执行 repin(重新锁定依赖版本),读完后可在 Kong 的 Bazel 构建环境中正确升级和审计 Rust 依赖。

背景:Kong 为什么要为 Rust 依赖单独维护锁文件目录

Kong 的核心路由模块 atc-router 是用 Rust 编写的(当前锁定版本为 1.7.1,可查 crate_locks/atc_router.Cargo.lock[[package]] name = "atc-router" 条目)。Kong 的发布构建已经迁移到 Bazel:Rust 代码通过 rules_rust 构建为 rust_shared_library,最终产物被 OpenResty/Lua 侧加载。

Bazel 的构建模型要求所有外部依赖的解析结果在构建开始之前就完全确定,因此 Rust 生态中“运行时由 cargo 在线解析”的惯例在 Bazel 世界行不通。crate_locks/ 目录就是为此而设:crate_locks/README.md 明确写道,该目录存放 Rust 依赖的锁文件(lock files),目前包含两个文件:

两种锁文件的分工:Cargo.lock 与 xxx.lock

crate_locks/README.md 对两类文件给出了简短但关键的定义:

  • xxx.Cargo.lock:由 cargo 生成的标准锁文件(记录每个依赖的精确版本与 checksum),但“为了让 rules_rust 满意,我们是用 Bazel 来生成它的”——即它由 Bazel 的 repin 流程驱动 cargo 重新计算,而不是开发者手动运行 cargo update
  • xxx.lock:由 Bazel(rules_rust 的 crate_universe 机制)生成,直接用于 rules_rust 的依赖解析,是可复现构建(reproducibility)的关键输入

从仓库中两个锁文件的实际内容可以印证这种分工:

  • atc_router.Cargo.lock 是标准 TOML 格式,头部注释 # This file is automatically @generated by Cargoversion = 3,每个 [[package]] 段包含 nameversionsource(crates.io 索引地址)与 checksum,例如 aho-corasick 1.1.3 的 sha256 为 8e60d3...。atc-router 自身的直接依赖包括 bitflagscidrcriterionfnvlazy_staticpestpest_deriveregexserdeserde_regexuuid
  • atc_router.lock 是 JSON 格式(约 5591 行),顶层有一个 "checksum" 字段(整个文件的完整性校验),"crates" 字段下每个键(如 "aho-corasick 1.1.3")记录了下载 URL(https://static.crates.io/crates/...)、逐文件的 sha256、crate 的构建 targets、edition、feature 集、依赖关系以及 license 信息。rules_rust 正是基于这份 JSON 在 Bazel 的 repository rule 阶段把每个 crate 物化为外部仓库。

Bazel 侧如何消费这两个文件

锁文件在 Bazel 侧的消费点在 build/kong_crate/deps.bzlkong_crate_repositories() 函数通过 rules_rust 的 crates_repository 规则声明了名为 atc_router_crate_index 的 crate 索引:

crates_repository(
    name = "atc_router_crate_index",
    cargo_lockfile = "//:crate_locks/atc_router.Cargo.lock",
    isolated = cargo_home_isolated,
    lockfile = "//:crate_locks/atc_router.lock",
    manifests = [
        "@atc_router//:Cargo.toml",
    ],
)

几个值得注意的细节:

  • 两个锁文件路径都以 //:crate_locks/... 显式指向仓库根下的 crate_locks/ 目录,这正是 README 中 repin 命令与文件命名能对应上的原因——repin 的对象名 atc_router_crate_index 就是这里的 name 字段;
  • isolated = cargo_home_isolated:默认使用隔离的 CARGO_HOME(首次 bootstrap 约需 2 分钟),避免污染开发者系统的 cargo 缓存;
  • 该函数同时通过 rust_register_toolchains 将 Rust 工具链钉死在 1.82.0(edition 2021,附 x86_64 与 aarch64 两套 tarball 的 sha256),见 build/kong_crate/deps.bzl,进一步保证跨机器构建一致。

crate 索引生成后会暴露一个 defs.bzl,由 build/kong_crate/crates.bzl 加载:

load("@atc_router_crate_index//:defs.bzl", atc_router_crate_repositories = "crate_repositories")

def kong_crates():
    atc_router_crate_repositories()

而真正编译 atc-router 的 build/openresty/atc_router/BUILD.atc_router.bazel 同样从该索引加载 aliasesall_crate_deps,用 rust_shared_library 规则以 default + ffi 两个 feature 构建共享库——所有 deps 全部来自 all_crate_deps(normal = True),即完全由锁文件解析出的依赖集合,构建时不会再去访问网络解析新版本。

如何 Repin:Bash 与 Fish 两种操作方式

Repin 的含义是:让 cargo 按当前 Cargo.toml 重新求解依赖版本,并同步刷新 crate 索引及其衍生的两个锁文件。crate_locks/README.md 给出的核心命令(Bash 版)为:

crates="atc_router_crate_index"
CARGO_BAZEL_REPIN=1 CARGO_BAZEL_REPIN_ONLY=$crates bazel sync --only=$crates
unset crates

Fish 版等价写法:

set -l crates \
    atc_router_crate_index
CARGO_BAZEL_REPIN=1 CARGO_BAZEL_REPIN_ONLY=$(string join ',' $crates) bazel sync --only=$(string join ',' $crates)
set -e crates

逐段拆解这条命令:

元素 作用
crates="atc_router_crate_index" 指定要 repin 的 crate 索引名,即 deps.bzlcrates_repositoryname;若仓库将来新增其它 crate 索引,只需在列表中追加
CARGO_BAZEL_REPIN=1 rules_rust 约定的开关,告诉 crate_universe 的 repository rule:本次运行允许调用 cargo 重新计算并写回锁文件(默认情况下该值是只读的)
CARGO_BAZEL_REPIN_ONLY=$crates 限定只刷新指定索引的锁文件,不影响其它索引
bazel sync --only=$crates 只触发该外部仓库的 fetch/sync,而不是全量同步,缩短操作时间

README 同时提示:更完整的 repin 说明请参考 rules_rust 项目文档(此处不再展开外部链接)。实际操作时的注意点:

  1. 由于 crates_repository 默认 isolated = True,首次 repin 会 bootstrap 一个隔离的 CARGO_HOME,耗时约 2 分钟;
  2. repin 完成后应检查 crate_locks/ 下两个文件是否成对更新——atc_router.Cargo.lock(版本/checksum 变化)与 atc_router.lock(JSON,含顶层 checksum 与每个 crate 的下载 sha256),两者必须一致地提交,否则 Bazel 构建与可复现性保证会被破坏;
  3. repin 是“有写权限”的特殊操作:日常构建时这些锁文件是只读输入,任何人在本地手动改 Cargo.lock 都不会被构建采纳,只有通过 CARGO_BAZEL_REPIN=1 流程重新生成才有效。

锁文件内容速览:以 aho-corasick 为例

对比同一个依赖在两份锁文件中的记录,可以直观理解两者格式差异:

atc_router.Cargo.lock(cargo 视角):

[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
 "memchr",
]

atc_router.lock(rules_rust 视角,节选):

"aho-corasick 1.1.3": {
  "name": "aho-corasick",
  "version": "1.1.3",
  "repository": {
    "Http": {
      "url": "https://static.crates.io/crates/aho-corasick/1.1.3/download",
      "sha256": "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
    }
  },
  "targets": [ { "Library": { "crate_name": "aho_corasick", "crate_root": "src/lib.rs", ... } } ]
}

两份文件中的 sha256 完全一致,说明 .lock(JSON)是以 Cargo.lock 的版本解析结果为基础、再补充 Bazel 物化所需的元数据(下载 URL、构建 targets、edition、license 等)。这正是 README 中“Cargo.lock 让 cargo 生态认账、xxx.lock 让 rules_rust 可复现构建”这句分工描述的具体体现。

小结

  • crate_locks/ 是 Kong Bazel 构建中 Rust 依赖的可复现性锚点:atc_router.Cargo.lock 记录版本与校验和,atc_router.lock 记录 rules_rust 物化每个 crate 所需的全部元数据;
  • 两者的消费入口是 build/kong_crate/deps.bzlcrates_repository,产物经 build/kong_crate/crates.bzl 注入到 build/openresty/atc_router/BUILD.atc_router.bazel 的编译依赖中;
  • 升级 Rust 依赖时,按 crate_locks/README.md 的 repin 流程执行 CARGO_BAZEL_REPIN=1 CARGO_BAZEL_REPIN_ONLY=atc_router_crate_index bazel sync --only=atc_router_crate_index,并成对提交更新后的两个锁文件。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384