Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit d772879

Browse files
committed
Auto merge of rust-lang#77762 - pietroalbini:dist-build-manifest, r=Mark-Simulacrum
Dist build manifest This PR makes two changes that should remove a significant chunk of the time spent in our release process: cloning the `rust-lang/rust` monorepo, all its submodules, and building `bootstrap` to then invoke `build-manifest`: * `build-manifest` doesn't rely on a clone of the monorepo being present anymore. The only remaining bit of information it fetched from it (the Rust version) is instead bundled in the binary. * A new "component" is added, `build-manifest`. That component includes a prebuilt version of the tool, and it's *not* included in the Rustup manifest. This will allow `promote-release` to directly invoke the tool without interacting with our build system. * The Linux x86_64 CI is changed to also build the component mentioned above. It's the only CI builder tasked to do so, and to cleanly support this a new `--include-default-paths` flag was added to `./x.py`. * The `BUILD_MANIFEST_NUM_THREADS` environment variable is added to configure the number of threads at runtime. This PR is best reviewed commit-by-commit. r? `@Mark-Simulacrum`
2 parents 2d6eccd + 0b7ee9d commit d772879

File tree

11 files changed

+127
-56
lines changed

11 files changed

+127
-56
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ dependencies = [
243243
"anyhow",
244244
"flate2",
245245
"hex 0.4.2",
246+
"num_cpus",
246247
"rayon",
247248
"serde",
248249
"serde_json",

src/bootstrap/builder.rs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -193,37 +193,37 @@ impl StepDescription {
193193
);
194194
}
195195

196-
if paths.is_empty() {
197-
for (desc, should_run) in v.iter().zip(should_runs) {
196+
if paths.is_empty() || builder.config.include_default_paths {
197+
for (desc, should_run) in v.iter().zip(&should_runs) {
198198
if desc.default && should_run.is_really_default {
199199
for pathset in &should_run.paths {
200200
desc.maybe_run(builder, pathset);
201201
}
202202
}
203203
}
204-
} else {
205-
for path in paths {
206-
// strip CurDir prefix if present
207-
let path = match path.strip_prefix(".") {
208-
Ok(p) => p,
209-
Err(_) => path,
210-
};
204+
}
211205

212-
let mut attempted_run = false;
213-
for (desc, should_run) in v.iter().zip(&should_runs) {
214-
if let Some(suite) = should_run.is_suite_path(path) {
215-
attempted_run = true;
216-
desc.maybe_run(builder, suite);
217-
} else if let Some(pathset) = should_run.pathset_for_path(path) {
218-
attempted_run = true;
219-
desc.maybe_run(builder, pathset);
220-
}
221-
}
206+
for path in paths {
207+
// strip CurDir prefix if present
208+
let path = match path.strip_prefix(".") {
209+
Ok(p) => p,
210+
Err(_) => path,
211+
};
222212

223-
if !attempted_run {
224-
panic!("error: no rules matched {}", path.display());
213+
let mut attempted_run = false;
214+
for (desc, should_run) in v.iter().zip(&should_runs) {
215+
if let Some(suite) = should_run.is_suite_path(path) {
216+
attempted_run = true;
217+
desc.maybe_run(builder, suite);
218+
} else if let Some(pathset) = should_run.pathset_for_path(path) {
219+
attempted_run = true;
220+
desc.maybe_run(builder, pathset);
225221
}
226222
}
223+
224+
if !attempted_run {
225+
panic!("error: no rules matched {}", path.display());
226+
}
227227
}
228228
}
229229
}
@@ -462,6 +462,7 @@ impl<'a> Builder<'a> {
462462
dist::LlvmTools,
463463
dist::RustDev,
464464
dist::Extended,
465+
dist::BuildManifest,
465466
dist::HashSign
466467
),
467468
Kind::Install => describe!(

src/bootstrap/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ pub struct Config {
6161
pub profiler: bool,
6262
pub ignore_git: bool,
6363
pub exclude: Vec<PathBuf>,
64+
pub include_default_paths: bool,
6465
pub rustc_error_format: Option<String>,
6566
pub json_output: bool,
6667
pub test_compare_mode: bool,
@@ -532,6 +533,7 @@ impl Config {
532533

533534
let mut config = Config::default_opts();
534535
config.exclude = flags.exclude;
536+
config.include_default_paths = flags.include_default_paths;
535537
config.rustc_error_format = flags.rustc_error_format;
536538
config.json_output = flags.json_output;
537539
config.on_fail = flags.on_fail;

src/bootstrap/dist.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2353,7 +2353,6 @@ impl Step for HashSign {
23532353
cmd.arg(today.trim());
23542354
cmd.arg(addr);
23552355
cmd.arg(&builder.config.channel);
2356-
cmd.arg(&builder.src);
23572356
cmd.env("BUILD_MANIFEST_LEGACY", "1");
23582357

23592358
builder.create_dir(&distdir(builder));
@@ -2584,3 +2583,70 @@ impl Step for RustDev {
25842583
Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
25852584
}
25862585
}
2586+
2587+
/// Tarball containing a prebuilt version of the build-manifest tool, intented to be used by the
2588+
/// release process to avoid cloning the monorepo and building stuff.
2589+
///
2590+
/// Should not be considered stable by end users.
2591+
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2592+
pub struct BuildManifest {
2593+
pub target: TargetSelection,
2594+
}
2595+
2596+
impl Step for BuildManifest {
2597+
type Output = PathBuf;
2598+
const DEFAULT: bool = false;
2599+
const ONLY_HOSTS: bool = true;
2600+
2601+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2602+
run.path("src/tools/build-manifest")
2603+
}
2604+
2605+
fn make_run(run: RunConfig<'_>) {
2606+
run.builder.ensure(BuildManifest { target: run.target });
2607+
}
2608+
2609+
fn run(self, builder: &Builder<'_>) -> PathBuf {
2610+
let build_manifest = builder.tool_exe(Tool::BuildManifest);
2611+
2612+
let name = pkgname(builder, "build-manifest");
2613+
let tmp = tmpdir(builder);
2614+
2615+
// Prepare the image.
2616+
let image = tmp.join("build-manifest-image");
2617+
let image_bin = image.join("bin");
2618+
let _ = fs::remove_dir_all(&image);
2619+
t!(fs::create_dir_all(&image_bin));
2620+
builder.install(&build_manifest, &image_bin.join("build-manifest"), 0o755);
2621+
2622+
// Prepare the overlay.
2623+
let overlay = tmp.join("build-manifest-overlay");
2624+
let _ = fs::remove_dir_all(&overlay);
2625+
builder.create_dir(&overlay);
2626+
builder.create(&overlay.join("version"), &builder.rust_version());
2627+
for file in &["COPYRIGHT", "LICENSE-APACHE", "LICENSE-MIT", "README.md"] {
2628+
builder.install(&builder.src.join(file), &overlay, 0o644);
2629+
}
2630+
2631+
// Create the final tarball.
2632+
let mut cmd = rust_installer(builder);
2633+
cmd.arg("generate")
2634+
.arg("--product-name=Rust")
2635+
.arg("--rel-manifest-dir=rustlib")
2636+
.arg("--success-message=build-manifest installed.")
2637+
.arg("--image-dir")
2638+
.arg(&image)
2639+
.arg("--work-dir")
2640+
.arg(&tmpdir(builder))
2641+
.arg("--output-dir")
2642+
.arg(&distdir(builder))
2643+
.arg("--non-installed-overlay")
2644+
.arg(&overlay)
2645+
.arg(format!("--package-name={}-{}", name, self.target.triple))
2646+
.arg("--legacy-manifest-dirs=rustlib,cargo")
2647+
.arg("--component-name=build-manifest");
2648+
2649+
builder.run(&mut cmd);
2650+
distdir(builder).join(format!("{}-{}.tar.gz", name, self.target.triple))
2651+
}
2652+
}

src/bootstrap/flags.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub struct Flags {
3030
pub cmd: Subcommand,
3131
pub incremental: bool,
3232
pub exclude: Vec<PathBuf>,
33+
pub include_default_paths: bool,
3334
pub rustc_error_format: Option<String>,
3435
pub json_output: bool,
3536
pub dry_run: bool,
@@ -137,6 +138,11 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
137138
opts.optmulti("", "host", "host targets to build", "HOST");
138139
opts.optmulti("", "target", "target targets to build", "TARGET");
139140
opts.optmulti("", "exclude", "build paths to exclude", "PATH");
141+
opts.optflag(
142+
"",
143+
"include-default-paths",
144+
"include default paths in addition to the provided ones",
145+
);
140146
opts.optopt("", "on-fail", "command to run on failure", "CMD");
141147
opts.optflag("", "dry-run", "dry run; don't build anything");
142148
opts.optopt(
@@ -618,6 +624,7 @@ Arguments:
618624
.into_iter()
619625
.map(|p| p.into())
620626
.collect::<Vec<_>>(),
627+
include_default_paths: matches.opt_present("include-default-paths"),
621628
deny_warnings: parse_deny_warnings(&matches),
622629
llvm_skip_rebuild: matches.opt_str("llvm-skip-rebuild").map(|s| s.to_lowercase()).map(
623630
|s| s.parse::<bool>().expect("`llvm-skip-rebuild` should be either true or false"),

src/bootstrap/run.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ impl Step for BuildManifest {
7777
cmd.arg(today.trim());
7878
cmd.arg(addr);
7979
cmd.arg(&builder.config.channel);
80-
cmd.arg(&builder.src);
8180

8281
builder.create_dir(&distdir(builder));
8382
builder.run(&mut cmd);

src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ ENV RUST_CONFIGURE_ARGS \
9898
--set llvm.thin-lto=true \
9999
--set llvm.ninja=false \
100100
--set rust.jemalloc
101-
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
101+
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS \
102+
--include-default-paths \
103+
src/tools/build-manifest
102104
ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
103105

104106
# This is the only builder which will create source tarballs

src/tools/build-manifest/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ tar = "0.4.29"
1414
sha2 = "0.9.1"
1515
rayon = "1.3.1"
1616
hex = "0.4.2"
17+
num_cpus = "1.13.0"

src/tools/build-manifest/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ Then, you can generate the manifest and all the packages from `path/to/dist` to
2121

2222
```
2323
$ cargo +nightly run path/to/dist path/to/output 1970-01-01 http://example.com \
24-
CHANNEL path/to/rust/repo
24+
CHANNEL VERSION
2525
```
2626

2727
Remember to replace `CHANNEL` with the channel you produced dist artifacts of
28-
and `path/to/rust/repo` with the path to your checkout of the Rust repository.
28+
and `VERSION` with the current Rust version.

src/tools/build-manifest/src/main.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,23 +205,27 @@ fn main() {
205205
//
206206
// Once the old release process is fully decommissioned, the environment variable, all the
207207
// related code in this tool and ./x.py dist hash-and-sign can be removed.
208-
let legacy = env::var("BUILD_MANIFEST_LEGACY").is_ok();
209-
210-
// Avoid overloading the old server in legacy mode.
211-
if legacy {
212-
rayon::ThreadPoolBuilder::new()
213-
.num_threads(1)
214-
.build_global()
215-
.expect("failed to initialize Rayon");
216-
}
208+
let legacy = env::var_os("BUILD_MANIFEST_LEGACY").is_some();
209+
210+
let num_threads = if legacy {
211+
// Avoid overloading the old server in legacy mode.
212+
1
213+
} else if let Some(num) = env::var_os("BUILD_MANIFEST_NUM_THREADS") {
214+
num.to_str().unwrap().parse().expect("invalid number for BUILD_MANIFEST_NUM_THREADS")
215+
} else {
216+
num_cpus::get()
217+
};
218+
rayon::ThreadPoolBuilder::new()
219+
.num_threads(num_threads)
220+
.build_global()
221+
.expect("failed to initialize Rayon");
217222

218223
let mut args = env::args().skip(1);
219224
let input = PathBuf::from(args.next().unwrap());
220225
let output = PathBuf::from(args.next().unwrap());
221226
let date = args.next().unwrap();
222227
let s3_address = args.next().unwrap();
223228
let channel = args.next().unwrap();
224-
let monorepo_path = args.next().unwrap();
225229

226230
// Do not ask for a passphrase while manually testing
227231
let mut passphrase = String::new();
@@ -231,7 +235,7 @@ fn main() {
231235
}
232236

233237
Builder {
234-
versions: Versions::new(&channel, &input, Path::new(&monorepo_path)).unwrap(),
238+
versions: Versions::new(&channel, &input).unwrap(),
235239

236240
input,
237241
output,

0 commit comments

Comments
 (0)