File: rust-vendor-std.patch

package info (click to toggle)
firefox 147.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,683,324 kB
  • sloc: cpp: 7,607,156; javascript: 6,532,492; ansic: 3,775,158; python: 1,415,368; xml: 634,556; asm: 438,949; java: 186,241; sh: 62,751; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (116 lines) | stat: -rw-r--r-- 5,368 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
Teaches Rust's build system to vendor `std`'s dependencies into the
`rust-src` component.

This was originally landed in <https://github.com/rust-lang/rust/pull/78790>,
and <https://github.com/rust-lang/cargo/pull/8834>, but was backed out for
causing breakage in other situations.

Since then, things have changed in cargo, such that it is now possible to use
a simpler approach that only relies on tweaking what is shipped in rust.

diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 4957de2e1b7..b903e1be4aa 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -941,6 +941,101 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
             &dst_src,
         );
 
+        // cargo's -Z build-std doesn't work properly alongside vendoring.
+        // To work around the issue, we vendor the libstd dependencies in the
+        // rust-src package, and alter libstd's Cargo.toml to contain
+        // patch.crates-io entries pointing to the vendored versions.
+        let root_dir = dst_src.join("library");
+        let root_lock = root_dir.join("Cargo.lock");
+        if root_lock.exists() {
+            use std::collections::HashMap;
+
+            use toml::map::Map;
+            use toml::Value;
+
+            let dst_vendor = dst_src.join("vendor");
+
+            let mut cmd = command(&builder.initial_cargo);
+            cmd.arg("vendor").arg(&dst_vendor).current_dir(&root_dir);
+            // library/std/Cargo.toml uses the `public-dependency` nightly cargo feature.
+            cmd.env("RUSTC_BOOTSTRAP", "1");
+            builder.info("Dist src");
+            let _time = timeit(builder);
+            builder.run(
+                &mut cmd,
+                crate::utils::exec::OutputMode::Print,
+                crate::utils::exec::OutputMode::Print,
+            );
+
+            // Ideally, we would add the .cargo/config.toml that `cargo vendor` outputs,
+            // but cargo doesn't read it when building libstd. So instead, we add
+            // [patch.crates-io] entries to Cargo.toml for all vendored packages.
+            let cargo_toml_path = root_lock.with_extension("toml");
+            let cargo_toml_str = t!(std::fs::read_to_string(&cargo_toml_path));
+            let mut manifest: Value = t!(toml::from_str(&cargo_toml_str));
+
+            let patch_table = t!(manifest
+                .get_mut("patch")
+                .and_then(|p| p.as_table_mut())
+                .and_then(|p| p.get_mut("crates-io"))
+                .and_then(|c| c.as_table_mut())
+                .ok_or("[patch.crates-io] section not found"));
+
+            let mut packages_by_name: HashMap<String, Vec<String>> = HashMap::new();
+
+            for entry in builder.read_dir(&dst_vendor) {
+                let path = entry.path();
+
+                // Check for Cargo.toml
+                let crate_cargo_toml_path = path.join("Cargo.toml");
+                if !crate_cargo_toml_path.exists() {
+                    continue;
+                }
+
+                // Parse package name from Cargo.toml
+                let crate_cargo_toml_str = t!(std::fs::read_to_string(&crate_cargo_toml_path));
+                let crate_cargo_toml: Value = t!(toml::from_str(&crate_cargo_toml_str));
+                let pkg_name = t!(crate_cargo_toml
+                    .get("package")
+                    .and_then(|p| p.get("name"))
+                    .and_then(|n| n.as_str())
+                    .ok_or("package.name not found"));
+                let dir_name = path.file_name().unwrap().to_string_lossy().into_owned();
+                packages_by_name
+                    .entry(pkg_name.to_string())
+                    .or_insert_with(Vec::new)
+                    .push(dir_name);
+            }
+
+            for (pkg_name, dirs) in &packages_by_name {
+                for dir_name in dirs.iter() {
+                    // What we want in the normal case:
+                    //   [patch.crates-io.crate]
+                    //   path = "../vendor/crate"
+                    // When the directory name is different (usually when it contains a
+                    // version) we want the following:
+                    //   [patch.crates-io.crate-version]
+                    //   package = "crate"
+                    //   path = "../vendor/crate-version"
+                    let mut patch_value = Map::new();
+                    let name = dir_name.replace('.', "_").replace('+', "_");
+                    if &name != pkg_name {
+                        patch_value.insert("package".to_string(), pkg_name.clone().into());
+                    }
+                    patch_value
+                        .insert("path".to_string(), format!("../vendor/{}", dir_name).into());
+                    patch_table.insert(name, patch_value.into());
+                }
+            }
+
+            // Cargo.toml may be a hardlink to the one in the repository, and
+            // we don't want to modify that, so break the hardlink first.
+            t!(std::fs::remove_file(&cargo_toml_path));
+
+            let new_cargo_toml = t!(toml::to_string_pretty(&manifest));
+            t!(std::fs::write(&cargo_toml_path, new_cargo_toml));
+        }
+
         tarball.generate()
     }
 }