Skip to content

Commit c70708e

Browse files
committed
refactor src/tools/x
Signed-off-by: ozkanonur <[email protected]>
1 parent 93fbc4a commit c70708e

File tree

8 files changed

+190
-136
lines changed

8 files changed

+190
-136
lines changed

src/bootstrap/bin/bootstrap-shim.rs

+52-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,56 @@
1-
use std::{env, process::Command};
1+
use std::{
2+
env, io,
3+
process::{self, Command, ExitStatus},
4+
};
25

36
use bootstrap::{Flags, MinimalConfig};
47

58
#[path = "../../../src/tools/x/src/main.rs"]
6-
mod run_python;
9+
mod x;
10+
11+
/// We are planning to exclude python logic from x script by executing bootstrap-shim
12+
/// immediately. Since `find_and_run_available_bootstrap_script` executes x script first,
13+
/// any changes on bootstrap will not be seen. To prevent this problem, in bootstrap-shim
14+
/// we want to call the python script directly.
15+
fn find_and_run_py_bootstrap_script() {
16+
#[cfg(unix)]
17+
fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
18+
use std::os::unix::process::CommandExt;
19+
Err(command.exec())
20+
}
21+
22+
#[cfg(not(unix))]
23+
fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
24+
command.status()
25+
}
26+
27+
let current_path = match env::current_dir() {
28+
Ok(dir) => dir,
29+
Err(err) => {
30+
eprintln!("Failed to get current directory: {err}");
31+
process::exit(1);
32+
}
33+
};
34+
35+
for dir in current_path.ancestors() {
36+
let candidate = dir.join("x.py");
37+
if candidate.exists() {
38+
let mut cmd: Command;
39+
cmd = Command::new(x::python());
40+
cmd.arg(&candidate).args(env::args().skip(1)).current_dir(dir);
41+
let result = exec_or_status(&mut cmd);
42+
43+
match result {
44+
Err(error) => {
45+
eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
46+
}
47+
Ok(status) => {
48+
process::exit(status.code().unwrap_or(1));
49+
}
50+
}
51+
}
52+
}
53+
}
754

855
fn main() {
956
let args = env::args().skip(1).collect::<Vec<_>>();
@@ -15,16 +62,17 @@ fn main() {
1562
let bootstrap_bin = if let Some(commit) = last_modified_bootstrap_commit(&config) {
1663
config.download_bootstrap(&commit)
1764
} else {
18-
return run_python::main();
65+
return find_and_run_py_bootstrap_script();
1966
};
2067

2168
let args: Vec<_> = std::env::args().skip(1).collect();
69+
println!("Running pre-compiled bootstrap binary");
2270
Command::new(bootstrap_bin).args(args).status().expect("failed to spawn bootstrap binairy");
2371
}
2472

2573
fn last_modified_bootstrap_commit(config: &MinimalConfig) -> Option<String> {
2674
config.last_modified_commit(
27-
&["src/bootstrap", "src/tools/build_helper"],
75+
&["src/bootstrap", "src/tools/build_helper", "src/tools/x"],
2876
"download-bootstrap",
2977
true,
3078
)

src/bootstrap/config.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ pub struct Config {
8484
pub jobs: Option<u32>,
8585
pub cmd: Subcommand,
8686
pub incremental: bool,
87-
pub dry_run: DryRun,
8887
/// Arguments appearing after `--` to be forwarded to tools,
8988
/// e.g. `--fix-broken` or test arguments.
9089
pub free_args: Vec<String>,
@@ -392,7 +391,7 @@ impl Target {
392391
/// `Config` structure.
393392
#[derive(Deserialize, Default)]
394393
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
395-
pub struct TomlConfig {
394+
struct TomlConfig {
396395
changelog_seen: Option<usize>,
397396
build: Option<Build>,
398397
install: Option<Install>,
@@ -748,17 +747,19 @@ impl Config {
748747
config
749748
}
750749

751-
pub fn parse(args: &[String], custom_toml_config: Option<TomlConfig>) -> Config {
750+
pub fn parse(args: &[String], custom_toml_config: Option<&str>) -> Config {
752751
let flags = Flags::parse(&args);
753752
let mut config = Config::default_opts();
754753

755-
let mut toml: TomlConfig = custom_toml_config.unwrap_or_else(|| {
754+
let mut toml: TomlConfig = if let Some(custom_toml_config) = custom_toml_config {
755+
toml::from_str(custom_toml_config).unwrap()
756+
} else {
756757
set_cfg_path_and_return_toml_cfg(
757758
config.src.clone(),
758759
flags.config.clone(),
759760
&mut config.config,
760761
)
761-
});
762+
};
762763

763764
config.minimal_config = MinimalConfig::parse(&flags, toml.build.clone());
764765

@@ -790,11 +791,6 @@ impl Config {
790791
crate::detail_exit(1);
791792
}
792793

793-
let build = toml.build.clone().unwrap_or_default();
794-
if let Some(file_build) = build.build.as_ref() {
795-
config.build = TargetSelection::from_user(file_build);
796-
};
797-
798794
if let Some(include) = &toml.profile {
799795
let mut include_path = config.src.clone();
800796
include_path.push("src");
@@ -807,6 +803,11 @@ impl Config {
807803

808804
config.changelog_seen = toml.changelog_seen;
809805

806+
let build = toml.build.unwrap_or_default();
807+
if let Some(file_build) = build.build {
808+
config.build = TargetSelection::from_user(&file_build);
809+
};
810+
810811
set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from)));
811812
// NOTE: Bootstrap spawns various commands with different working directories.
812813
// To avoid writing to random places on the file system, `config.out` needs to be an absolute path.

src/bootstrap/config/tests.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
use super::{Config, TomlConfig};
1+
use super::Config;
22
use std::{env, path::Path};
33

4-
fn toml(config: &str) -> TomlConfig {
5-
toml::from_str(config).unwrap()
6-
}
7-
84
fn parse(config: &str) -> Config {
9-
Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()], Some(toml(config)))
5+
Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()], Some(config))
106
}
117

128
#[test]

src/bootstrap/dist.rs

-1
Original file line numberDiff line numberDiff line change
@@ -2312,7 +2312,6 @@ impl Step for BootstrapShim {
23122312
const ONLY_HOSTS: bool = true;
23132313

23142314
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2315-
// Create this even with only `dist bootstrap` to avoid having to update all CI builders.
23162315
run.alias("bootstrap-shim")
23172316
}
23182317

src/bootstrap/download.rs

+94-94
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use once_cell::sync::OnceCell;
1111
use xz2::bufread::XzDecoder;
1212

1313
use crate::{
14-
min_config::RustfmtMetadata,
1514
llvm::detect_llvm_sha,
15+
min_config::RustfmtMetadata,
1616
t,
1717
util::{check_run, exe, output, program_out_of_date, try_run},
1818
Config, MinimalConfig,
@@ -343,6 +343,99 @@ enum DownloadSource {
343343
Dist,
344344
}
345345

346+
impl MinimalConfig {
347+
pub fn download_bootstrap(&self, commit: &str) -> PathBuf {
348+
self.verbose(&format!("downloading bootstrap from CI (commit {commit})"));
349+
let host = self.build.triple;
350+
let bin_root = self.out.join(host).join("bootstrap");
351+
let stamp = bin_root.join(".bootstrap-stamp");
352+
let bootstrap_bin = bin_root.join("bin").join("bootstrap");
353+
354+
if !bootstrap_bin.exists() || program_out_of_date(&stamp, commit) {
355+
let version = self.git_artifact_version_part(commit);
356+
let filename = format!("bootstrap-{version}-{host}.tar.xz");
357+
self.download_component(DownloadSource::CI, filename, "bootstrap", commit, "");
358+
if self.should_fix_bins_and_dylibs() {
359+
self.fix_bin_or_dylib(&bootstrap_bin);
360+
}
361+
t!(fs::write(stamp, commit));
362+
}
363+
364+
bootstrap_bin
365+
}
366+
367+
fn download_component(
368+
&self,
369+
mode: DownloadSource,
370+
filename: String,
371+
prefix: &str,
372+
key: &str,
373+
destination: &str,
374+
) {
375+
let cache_dst = self.out.join("cache");
376+
let cache_dir = cache_dst.join(key);
377+
if !cache_dir.exists() {
378+
t!(fs::create_dir_all(&cache_dir));
379+
}
380+
381+
let bin_root = self.out.join(self.build.triple).join(destination);
382+
let tarball = cache_dir.join(&filename);
383+
let (base_url, url, should_verify) = match mode {
384+
DownloadSource::CI => (
385+
self.stage0_metadata.config.artifacts_server.clone(),
386+
format!("{key}/{filename}"),
387+
false,
388+
),
389+
DownloadSource::Dist => {
390+
let dist_server = env::var("RUSTUP_DIST_SERVER")
391+
.unwrap_or(self.stage0_metadata.config.dist_server.to_string());
392+
// NOTE: make `dist` part of the URL because that's how it's stored in src/stage0.json
393+
(dist_server, format!("dist/{key}/{filename}"), true)
394+
}
395+
};
396+
397+
// For the beta compiler, put special effort into ensuring the checksums are valid.
398+
// FIXME: maybe we should do this for download-rustc as well? but it would be a pain to update
399+
// this on each and every nightly ...
400+
let checksum = if should_verify {
401+
let error = format!(
402+
"src/stage0.json doesn't contain a checksum for {url}. \
403+
Pre-built artifacts might not be available for this \
404+
target at this time, see https://doc.rust-lang.org/nightly\
405+
/rustc/platform-support.html for more information."
406+
);
407+
let sha256 = self.stage0_metadata.checksums_sha256.get(&url).expect(&error);
408+
if tarball.exists() {
409+
if self.verify(&tarball, sha256) {
410+
self.unpack(&tarball, &bin_root, prefix);
411+
return;
412+
} else {
413+
self.verbose(&format!(
414+
"ignoring cached file {} due to failed verification",
415+
tarball.display()
416+
));
417+
self.remove(&tarball);
418+
}
419+
}
420+
Some(sha256)
421+
} else if tarball.exists() {
422+
self.unpack(&tarball, &bin_root, prefix);
423+
return;
424+
} else {
425+
None
426+
};
427+
428+
self.download_file(&format!("{base_url}/{url}"), &tarball, "");
429+
if let Some(sha256) = checksum {
430+
if !self.verify(&tarball, sha256) {
431+
panic!("failed to verify {}", tarball.display());
432+
}
433+
}
434+
435+
self.unpack(&tarball, &bin_root, prefix);
436+
}
437+
}
438+
346439
/// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
347440
impl Config {
348441
pub(crate) fn maybe_download_rustfmt(&self) -> Option<PathBuf> {
@@ -553,96 +646,3 @@ impl Config {
553646
self.unpack(&tarball, &llvm_root, "rust-dev");
554647
}
555648
}
556-
557-
impl MinimalConfig {
558-
pub fn download_bootstrap(&self, commit: &str) -> PathBuf {
559-
self.verbose(&format!("downloading bootstrap from CI (commit {commit})"));
560-
let host = self.build.triple;
561-
let bin_root = self.out.join(host).join("bootstrap");
562-
let stamp = bin_root.join(".bootstrap-stamp");
563-
let bootstrap_bin = bin_root.join("bin").join("bootstrap");
564-
565-
if !bootstrap_bin.exists() || program_out_of_date(&stamp, commit) {
566-
let version = self.git_artifact_version_part(commit);
567-
let filename = format!("bootstrap-{version}-{host}.tar.xz");
568-
self.download_component(DownloadSource::CI, filename, "bootstrap", commit, "");
569-
if self.should_fix_bins_and_dylibs() {
570-
self.fix_bin_or_dylib(&bootstrap_bin);
571-
}
572-
t!(fs::write(stamp, commit));
573-
}
574-
575-
bootstrap_bin
576-
}
577-
578-
fn download_component(
579-
&self,
580-
mode: DownloadSource,
581-
filename: String,
582-
prefix: &str,
583-
key: &str,
584-
destination: &str,
585-
) {
586-
let cache_dst = self.out.join("cache");
587-
let cache_dir = cache_dst.join(key);
588-
if !cache_dir.exists() {
589-
t!(fs::create_dir_all(&cache_dir));
590-
}
591-
592-
let bin_root = self.out.join(self.build.triple).join(destination);
593-
let tarball = cache_dir.join(&filename);
594-
let (base_url, url, should_verify) = match mode {
595-
DownloadSource::CI => (
596-
self.stage0_metadata.config.artifacts_server.clone(),
597-
format!("{key}/{filename}"),
598-
false,
599-
),
600-
DownloadSource::Dist => {
601-
let dist_server = env::var("RUSTUP_DIST_SERVER")
602-
.unwrap_or(self.stage0_metadata.config.dist_server.to_string());
603-
// NOTE: make `dist` part of the URL because that's how it's stored in src/stage0.json
604-
(dist_server, format!("dist/{key}/{filename}"), true)
605-
}
606-
};
607-
608-
// For the beta compiler, put special effort into ensuring the checksums are valid.
609-
// FIXME: maybe we should do this for download-rustc as well? but it would be a pain to update
610-
// this on each and every nightly ...
611-
let checksum = if should_verify {
612-
let error = format!(
613-
"src/stage0.json doesn't contain a checksum for {url}. \
614-
Pre-built artifacts might not be available for this \
615-
target at this time, see https://doc.rust-lang.org/nightly\
616-
/rustc/platform-support.html for more information."
617-
);
618-
let sha256 = self.stage0_metadata.checksums_sha256.get(&url).expect(&error);
619-
if tarball.exists() {
620-
if self.verify(&tarball, sha256) {
621-
self.unpack(&tarball, &bin_root, prefix);
622-
return;
623-
} else {
624-
self.verbose(&format!(
625-
"ignoring cached file {} due to failed verification",
626-
tarball.display()
627-
));
628-
self.remove(&tarball);
629-
}
630-
}
631-
Some(sha256)
632-
} else if tarball.exists() {
633-
self.unpack(&tarball, &bin_root, prefix);
634-
return;
635-
} else {
636-
None
637-
};
638-
639-
self.download_file(&format!("{base_url}/{url}"), &tarball, "");
640-
if let Some(sha256) = checksum {
641-
if !self.verify(&tarball, sha256) {
642-
panic!("failed to verify {}", tarball.display());
643-
}
644-
}
645-
646-
self.unpack(&tarball, &bin_root, prefix);
647-
}
648-
}

src/bootstrap/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ mod format;
5454
mod install;
5555
mod llvm;
5656
mod metadata;
57-
mod render_tests;
5857
mod min_config;
58+
mod render_tests;
5959
mod run;
6060
mod sanity;
6161
mod setup;
@@ -90,8 +90,8 @@ use crate::cache::{Interned, INTERNER};
9090
pub use crate::config::Config;
9191
pub use crate::flags::Flags;
9292
pub use crate::flags::Subcommand;
93-
use termcolor::{ColorChoice, StandardStream, WriteColor};
9493
pub use crate::min_config::MinimalConfig;
94+
use termcolor::{ColorChoice, StandardStream, WriteColor};
9595

9696
const LLVM_TOOLS: &[&str] = &[
9797
"llvm-cov", // used to generate coverage report

0 commit comments

Comments
 (0)