bootstrap/core/build_steps/
vendor.rs

1//! Handles the vendoring process for the bootstrap system.
2//!
3//! This module ensures that all required Cargo dependencies are gathered
4//! and stored in the `<src>/<VENDOR_DIR>` directory.
5use std::path::PathBuf;
6
7use crate::core::build_steps::tool::SUBMODULES_FOR_RUSTBOOK;
8use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
9use crate::utils::exec::command;
10
11/// The name of the directory where vendored dependencies are stored.
12pub const VENDOR_DIR: &str = "vendor";
13
14/// Returns the cargo workspaces to vendor for `x vendor` and dist tarballs.
15///
16/// Returns a `Vec` of `(path_to_manifest, submodules_required)` where
17/// `path_to_manifest` is the cargo workspace, and `submodules_required` is
18/// the set of submodules that must be available.
19pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'static str>)> {
20    [
21        ("src/tools/cargo/Cargo.toml", vec!["src/tools/cargo"]),
22        ("src/tools/rust-analyzer/Cargo.toml", vec![]),
23        ("compiler/rustc_codegen_cranelift/Cargo.toml", vec![]),
24        ("compiler/rustc_codegen_gcc/Cargo.toml", vec![]),
25        ("library/Cargo.toml", vec![]),
26        ("src/bootstrap/Cargo.toml", vec![]),
27        ("src/tools/rustbook/Cargo.toml", SUBMODULES_FOR_RUSTBOOK.into()),
28        ("src/tools/rustc-perf/Cargo.toml", vec!["src/tools/rustc-perf"]),
29        ("src/tools/opt-dist/Cargo.toml", vec![]),
30        ("src/doc/book/packages/trpl/Cargo.toml", vec![]),
31    ]
32    .into_iter()
33    .map(|(path, submodules)| (builder.src.join(path), submodules))
34    .collect()
35}
36
37/// Defines the vendoring step in the bootstrap process.
38///
39/// This step executes `cargo vendor` to collect all dependencies
40/// and store them in the `<src>/<VENDOR_DIR>` directory.
41#[derive(Debug, Clone, Hash, PartialEq, Eq)]
42pub(crate) struct Vendor {
43    /// Additional paths to synchronize during vendoring.
44    pub(crate) sync_args: Vec<PathBuf>,
45    /// Determines whether vendored dependencies use versioned directories.
46    pub(crate) versioned_dirs: bool,
47    /// The root directory of the source code.
48    pub(crate) root_dir: PathBuf,
49    /// The target directory for storing vendored dependencies.
50    pub(crate) output_dir: PathBuf,
51}
52
53impl Step for Vendor {
54    type Output = VendorOutput;
55    const DEFAULT: bool = true;
56    const ONLY_HOSTS: bool = true;
57
58    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
59        run.alias("placeholder").default_condition(true)
60    }
61
62    fn make_run(run: RunConfig<'_>) {
63        run.builder.ensure(Vendor {
64            sync_args: run.builder.config.cmd.vendor_sync_args(),
65            versioned_dirs: run.builder.config.cmd.vendor_versioned_dirs(),
66            root_dir: run.builder.src.clone(),
67            output_dir: run.builder.src.join(VENDOR_DIR),
68        });
69    }
70
71    /// Executes the vendoring process.
72    ///
73    /// This function runs `cargo vendor` and ensures all required submodules
74    /// are initialized before vendoring begins.
75    fn run(self, builder: &Builder<'_>) -> Self::Output {
76        builder.info(&format!("Vendoring sources to {:?}", self.root_dir));
77
78        let mut cmd = command(&builder.initial_cargo);
79        cmd.arg("vendor");
80
81        if self.versioned_dirs {
82            cmd.arg("--versioned-dirs");
83        }
84
85        let to_vendor = default_paths_to_vendor(builder);
86        // These submodules must be present for `x vendor` to work.
87        for (_, submodules) in &to_vendor {
88            for submodule in submodules {
89                builder.build.require_submodule(submodule, None);
90            }
91        }
92
93        // Sync these paths by default.
94        for (p, _) in &to_vendor {
95            cmd.arg("--sync").arg(p);
96        }
97
98        // Also sync explicitly requested paths.
99        for sync_arg in self.sync_args {
100            cmd.arg("--sync").arg(sync_arg);
101        }
102
103        // Will read the libstd Cargo.toml
104        // which uses the unstable `public-dependency` feature.
105        cmd.env("RUSTC_BOOTSTRAP", "1");
106        cmd.env("RUSTC", &builder.initial_rustc);
107
108        cmd.current_dir(self.root_dir).arg(&self.output_dir);
109
110        let config = cmd.run_capture_stdout(builder);
111        VendorOutput { config: config.stdout() }
112    }
113}
114
115/// Stores the result of the vendoring step.
116#[derive(Debug, Clone)]
117pub(crate) struct VendorOutput {
118    pub(crate) config: String,
119}