ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

深入解析 rustc-std-workspace-core:Rust 标准库依赖 crates.io 生态的桥梁与编译期 shim

深入解析 rustc-std-workspace-core:Rust 标准库依赖 crates.io 生态的桥梁与编译期 shim 深入解析 rustc-std-workspace-coreRust 标准库依赖 crates.io 生态的桥梁与编译期 shim【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust导读rustc-std-workspace-core是 Rust 编译器仓库rustc 源码树中一个看似空却至关重要的 shim crate它本身几乎不包含任何业务逻辑却承担着让标准库std/alloc/core能够安全依赖 crates.io 上第三方 crate、同时把这些依赖的core引用指回仓库内真实libcore的重任。本文以 library/rustc-std-workspace-core/README.md 为主线结合仓库内的 Cargo.toml 与 lib.rs 源码讲清楚它诞生的背景、工作原理、[patch]机制、package重命名技巧以及它如何顺带把compiler-builtins拉进 crate 依赖图。一、为什么需要这样一个空 crate标准库与 crates.io 的依赖困境1.1 标准库自身要依赖第三方 crate从源码结构看标准库并非一个完全自给自足的孤岛。仓库中 library/ 目录下的std、alloc等 crate 会依赖 crates.io 上发布的部分 crate例如compiler-builtins这类底层支持库。这里立刻产生一个矛盾crates.io 上发布的第三方 crate其源码里写的是对 crates.io 版本core的依赖这是正常的extern crate core世界而 rustc 仓库构建标准库时core必须是当前仓库里那份正在编译的源码绝不可能是 crates.io 上已发布的旧版本。如果放任第三方 crate 去依赖 crates.io 上的core就会得到两份互不相同的core标准库与第三方 crate 之间的类型、core::*符号都将无法统一编译必然失败。1.2 解决思路shim [patch]双保险README 给出的方案很巧妙让 crates.io 上的 crate 不要直接依赖 crates.io 的core而是依赖一个空壳 crate——rustc-std-workspace-core。这个空壳 crate 在 crates.io 上是空的只声明依赖、几乎无内容但在 rustc 仓库内部则通过 Cargo 的[patch]机制被整体替换成本仓库内的 shim 版本。这样整条链路变成crates.io 第三方 crate │ 依赖被重命名为 core ▼ rustc-std-workspace-corecrates.io 上是空壳 │ [patch.crates-io] 覆盖 ▼ rustc-std-workspace-core仓库内 shim见 library/rustc-std-workspace-core │ pub use core::* ▼ libcore仓库内真实 core 源码最终效果正如 README 所述crates.io 上的 crate 会绘制出一条指向本仓库libcore的依赖边从而保证 Cargo 能用同一份core把所有 crate 成功构建出来。二、shim 的真实源码长什么样2.1lib.rs全部内容只有三行仓库内 shim 的实现位于 library/rustc-std-workspace-core/lib.rs完整源码如下#![feature(no_core)] #![no_core] pub use core::*; // Crate must be brought into scope so it appears in the crate graph for anything that // depends on rustc-std-workspace-core. use compiler_builtins as _;逐行拆解#![feature(no_core)]#![no_core]声明本 crate 自身不隐式链接core允许它直接对真实core做pub use重导出pub use core::*;这是 shim 的灵魂——把libcore的全部公开内容原样重导出。凡是依赖了rustc-std-workspace-core的 crate就等于直接看到了仓库内core的完整 APIuse compiler_builtins as _;以匿名导入as _方式把compiler-builtins强制拉进 crate 依赖图这是后面统一配置 compiler-builtins一节的关键。2.2Cargo.toml版本、edition 与依赖声明对应的清单文件 library/rustc-std-workspace-core/Cargo.toml 也很有信息量cargo-features [public-dependency] [package] name rustc-std-workspace-core version 1.99.0 license MIT OR Apache-2.0 description Hack for the compilers own build system edition 2024 [lib] path lib.rs test false bench false doc false [dependencies] core { path ../core, public true } compiler_builtins { path ../compiler-builtins/compiler-builtins, features [ compiler-builtins, ] }值得注意的细节description直言不讳地写着Hack for the compilers own build system为编译器自身构建系统设计的 Hack说明官方也认可这是一个工程性技巧而非常规设计模式core { path ../core, public true }以相对路径指向仓库内 library/core并借助public-dependencycargo 特性把core声明为公开依赖使得 shim 对core的重导出在依赖图中合法可见test false、bench false、doc false该 crate 不参与测试、基准与文档构建进一步印证它只是构建期粘合剂compiler_builtins依赖显式开启compiler-builtinsfeature把底层内建函数库一并纳入依赖图。三、[patch]crates.io 空壳如何被仓库内版本替换3.1 仓库根工作区的 patch 配置真正让这套机制运转起来的是library工作区的[patch.crates-io]配置见 library/Cargo.toml[patch.crates-io] # See comments in library/rustc-std-workspace-core/README.md for whats going on here rustc-std-workspace-core { path rustc-std-workspace-core } rustc-std-workspace-alloc { path rustc-std-workspace-alloc } rustc-std-workspace-std { path rustc-std-workspace-std }这段配置的含义工作区内任何对 crates.io 上rustc-std-workspace-core的依赖请求都会被 Cargo 解析为path rustc-std-workspace-core即 library/rustc-std-workspace-core同理还有rustc-std-workspace-alloc见 library/rustc-std-workspace-alloc与rustc-std-workspace-std见 library/rustc-std-workspace-std两个配套 shim分别对应alloc与std的场景配置注释也明确指引读者想了解这里发生了什么请看library/rustc-std-workspace-core/README.md——即本文所依据的关联文档。从构建系统侧也能看到它的地位src/bootstrap的多个 CLI 路径快照如 x_build.snap、x_check.snap都把library/rustc-std-workspace-core列为构建/检查目标之一说明./x.py build、./x.py check等标准操作都会显式包含这个 crate。3.2 crates.io 版本与仓库内版本的分工需要注意的是src/rustc-std-workspace目录下存放的是发布到 crates.io 用的版本详见 src/rustc-std-workspace/README.md 的说明它只是一个占位空壳而library/下的才是 rustc 工作区实际使用的 shim。二者同名同源职责不同位置角色内容src/rustc-std-workspacecrates.io 发布版本空壳占位供第三方 crate 声明依赖library/rustc-std-workspace-core仓库内实际使用真实 shim重导出仓库内core并引入compiler-builtins四、package重命名技巧把依赖伪装成core4.1 为什么必须叫corerustc 编译器在编译每个 crate 时都会隐式注入extern crate core;指令即使源码里没有显式写出。这意味着任何被编译的 crate其外部依赖中必须存在一个能被解析为core的 crate否则编译直接报错。但第三方 crate 在 crates.io 上依赖的显然是 crates.io 版core如果它们能直接依赖core的话。为了把这份依赖偷梁换柱成rustc-std-workspace-coreREADME 给出了标准写法core { version 1.0.0, optional true, package rustc-std-workspace-core }逐字段解读core {...}这是依赖名即 crate 在被依赖方代码中呈现的名字package rustc-std-workspace-core指明实际要解析的 crates.io 包名是rustc-std-workspace-core而不是crates.io 上那个真实的coreversion 1.0.0匹配 crates.io 上空壳包的版本号optional true声明为可选依赖给下游 crate 留出按 feature 开启的灵活性。4.2 从core到--extern的转换通过package键完成重命名后当 Cargo 调用 rustc 编译依赖方时传入的链接参数会变成--extern core.../librustc_std_workspace_core-XXXXXXX.rlib这条命令中--extern core是给编译器的外部 crate 声明名字依然是core右侧的 rlib 文件则是rustc-std-workspace-core的产物文件名里的rustc_std_workspace_core是包名转换后的形式。于是编译器视角下名为core的外部 crate实际被满足为 shim crate而 shim 又pub use core::*重导出了真实libcore环环相扣最终所有 crate 拿到的core都是仓库内正在构建的那份。五、附带价值统一把compiler-builtins纳入依赖图5.1 问题重复依赖与重复配置compiler-builtins编译器内建函数库提供整数除法、内存操作等底层实现是标准库体系的重要支撑。但并不是每个 crate 都直接依赖它——除了std和alloclibrary/下还有其他 crate。如果要求这些 crate 各自同时声明依赖core和compiler-builtins就会造成大量重复配置且极易漏配或版本不一致。5.2 解法由 shim 一家承担README 明确指出rustc-std-workspace-core的另一个职责就是确保compiler-builtins出现在 crate 依赖图中。实现方式就在 lib.rs 的那行use compiler_builtins as _;as _是 Rust 的匿名导入写法只要求该 crate 被链接进依赖图不引入任何名字由于compiler-builtins已作为 shim 的依赖声明在 Cargo.toml 中所有依赖 shim 的 crate 都间接把compiler-builtins带进了构建图。这样一来compiler-builtins的引入与配置只需在一个地方shim 的Cargo.toml完成即可无需在library/下各个 crate 中重复声明。5.3 配套 shimalloc 与 std 的同款套路作为对照另外两个 shim 采用了几乎一致的思路library/rustc-std-workspace-alloc/lib.rs#![feature(no_core)] #![no_core] // See rustc-std-workspace-core for why this crate is needed. // Rename the crate to avoid conflicting with the alloc module in alloc. extern crate alloc as foo; pub use foo::*;它通过extern crate alloc as foo;将alloc重命名为foo后重导出避免与alloccrate 内部的alloc模块名冲突library/rustc-std-workspace-std/lib.rs#![feature(restricted_std)] pub use std::*;针对std场景使用restricted_std特性做受限重导出。三个 shim 覆盖core、alloc、std三层构成完整的 crates.io ↔ 仓库内标准库桥接体系。六、整体工作流回顾与 FAQ6.1 一次完整的依赖解析流程crates.io 上的某个 crate 按 README 约定声明core { version 1.0.0, optional true, package rustc-std-workspace-core }该 crate 被引入 rustc 仓库工作区例如作为library/下某 crate 的依赖时Cargo 依据 library/Cargo.toml 的[patch.crates-io]将rustc-std-workspace-core解析为仓库内 shimCargo 调用 rustc 时生成--extern core.../librustc_std_workspace_core-*.rlib满足编译器隐式注入的extern crate coreshim 的pub use core::*;把真实libcore的 API 全部暴露给依赖方同时use compiler_builtins as _;确保底层内建函数库进入依赖图最终所有 crate 共享同一份仓库内core标准库与第三方 crate 的类型系统完全统一构建成功。6.2 常见疑问Qshim 为什么不直接叫coreAcrates.io 上core这个名字属于真实的libcore发布物。为了避免与它冲突、也为了让[patch]可以精确命中shim 保留了独立包名rustc-std-workspace-core仅在依赖声明一侧用package键完成重命名。Q#![no_core]起什么作用A它告诉编译器本 crate 不隐式引入core避免与后续pub use core::*;的重导出发生自我引用式的循环解析是让 shim 能干净地重导出外部core的前提。Q普通应用开发者需要关心这个 crate 吗A不需要。它是 rustc 自举/标准库构建链路的内部基础设施属于编译器自己的构建系统 HackCargo.toml 的 description 原话。普通开发者只有在阅读 rustc 源码、研究标准库构建流程或自己编写被标准库依赖的 crates.io crate 时才需要理解这套package[patch]约定。七、深入阅读指引如果希望继续深入这套机制的实现细节可以在仓库中按以下路径展开阅读关联文档library/rustc-std-workspace-core/README.md本文主线来源shim 源码与清单library/rustc-std-workspace-core/lib.rs、library/rustc-std-workspace-core/Cargo.toml工作区 patch 配置library/Cargo.toml配套 shimlibrary/rustc-std-workspace-alloc/lib.rs、library/rustc-std-workspace-std/lib.rscrates.io 发布版空壳src/rustc-std-workspace底层支撑库library/compiler-builtins、library/core构建系统对该 crate 的纳入x_build.snap理解了这个空 crate之后再回头看标准库庞大的构建流程你会发现正是这些看似不起眼的构建期 shim悄无声息地维系着 Rust 标准库与整个 crates.io 生态之间的类型统一与依赖一致性。【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表