Skip to content

Commit 6a3d223

Browse files
committed
refactor src/tools/x
Signed-off-by: ozkanonur <[email protected]>
1 parent ce85672 commit 6a3d223

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>,
@@ -391,7 +390,7 @@ impl Target {
391390
/// `Config` structure.
392391
#[derive(Deserialize, Default)]
393392
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
394-
pub struct TomlConfig {
393+
struct TomlConfig {
395394
changelog_seen: Option<usize>,
396395
build: Option<Build>,
397396
install: Option<Install>,
@@ -745,17 +744,19 @@ impl Config {
745744
config
746745
}
747746

748-
pub fn parse(args: &[String], custom_toml_config: Option<TomlConfig>) -> Config {
747+
pub fn parse(args: &[String], custom_toml_config: Option<&str>) -> Config {
749748
let flags = Flags::parse(&args);
750749
let mut config = Config::default_opts();
751750

752-
let mut toml: TomlConfig = custom_toml_config.unwrap_or_else(|| {
751+
let mut toml: TomlConfig = if let Some(custom_toml_config) = custom_toml_config {
752+
toml::from_str(custom_toml_config).unwrap()
753+
} else {
753754
set_cfg_path_and_return_toml_cfg(
754755
config.src.clone(),
755756
flags.config.clone(),
756757
&mut config.config,
757758
)
758-
});
759+
};
759760

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

@@ -787,11 +788,6 @@ impl Config {
787788
crate::detail_exit(1);
788789
}
789790

790-
let build = toml.build.clone().unwrap_or_default();
791-
if let Some(file_build) = build.build.as_ref() {
792-
config.build = TargetSelection::from_user(file_build);
793-
};
794-
795791
if let Some(include) = &toml.profile {
796792
let mut include_path = config.src.clone();
797793
include_path.push("src");
@@ -804,6 +800,11 @@ impl Config {
804800

805801
config.changelog_seen = toml.changelog_seen;
806802

803+
let build = toml.build.unwrap_or_default();
804+
if let Some(file_build) = build.build {
805+
config.build = TargetSelection::from_user(&file_build);
806+
};
807+
807808
set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from)));
808809
// NOTE: Bootstrap spawns various commands with different working directories.
809810
// 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> {
@@ -509,96 +602,3 @@ impl Config {
509602
self.unpack(&tarball, &llvm_root, "rust-dev");
510603
}
511604
}
512-
513-
impl MinimalConfig {
514-
pub fn download_bootstrap(&self, commit: &str) -> PathBuf {
515-
self.verbose(&format!("downloading bootstrap from CI (commit {commit})"));
516-
let host = self.build.triple;
517-
let bin_root = self.out.join(host).join("bootstrap");
518-
let stamp = bin_root.join(".bootstrap-stamp");
519-
let bootstrap_bin = bin_root.join("bin").join("bootstrap");
520-
521-
if !bootstrap_bin.exists() || program_out_of_date(&stamp, commit) {
522-
let version = self.git_artifact_version_part(commit);
523-
let filename = format!("bootstrap-{version}-{host}.tar.xz");
524-
self.download_component(DownloadSource::CI, filename, "bootstrap", commit, "");
525-
if self.should_fix_bins_and_dylibs() {
526-
self.fix_bin_or_dylib(&bootstrap_bin);
527-
}
528-
t!(fs::write(stamp, commit));
529-
}
530-
531-
bootstrap_bin
532-
}
533-
534-
fn download_component(
535-
&self,
536-
mode: DownloadSource,
537-
filename: String,
538-
prefix: &str,
539-
key: &str,
540-
destination: &str,
541-
) {
542-
let cache_dst = self.out.join("cache");
543-
let cache_dir = cache_dst.join(key);
544-
if !cache_dir.exists() {
545-
t!(fs::create_dir_all(&cache_dir));
546-
}
547-
548-
let bin_root = self.out.join(self.build.triple).join(destination);
549-
let tarball = cache_dir.join(&filename);
550-
let (base_url, url, should_verify) = match mode {
551-
DownloadSource::CI => (
552-
self.stage0_metadata.config.artifacts_server.clone(),
553-
format!("{key}/{filename}"),
554-
false,
555-
),
556-
DownloadSource::Dist => {
557-
let dist_server = env::var("RUSTUP_DIST_SERVER")
558-
.unwrap_or(self.stage0_metadata.config.dist_server.to_string());
559-
// NOTE: make `dist` part of the URL because that's how it's stored in src/stage0.json
560-
(dist_server, format!("dist/{key}/{filename}"), true)
561-
}
562-
};
563-
564-
// For the beta compiler, put special effort into ensuring the checksums are valid.
565-
// FIXME: maybe we should do this for download-rustc as well? but it would be a pain to update
566-
// this on each and every nightly ...
567-
let checksum = if should_verify {
568-
let error = format!(
569-
"src/stage0.json doesn't contain a checksum for {url}. \
570-
Pre-built artifacts might not be available for this \
571-
target at this time, see https://doc.rust-lang.org/nightly\
572-
/rustc/platform-support.html for more information."
573-
);
574-
let sha256 = self.stage0_metadata.checksums_sha256.get(&url).expect(&error);
575-
if tarball.exists() {
576-
if self.verify(&tarball, sha256) {
577-
self.unpack(&tarball, &bin_root, prefix);
578-
return;
579-
} else {
580-
self.verbose(&format!(
581-
"ignoring cached file {} due to failed verification",
582-
tarball.display()
583-
));
584-
self.remove(&tarball);
585-
}
586-
}
587-
Some(sha256)
588-
} else if tarball.exists() {
589-
self.unpack(&tarball, &bin_root, prefix);
590-
return;
591-
} else {
592-
None
593-
};
594-
595-
self.download_file(&format!("{base_url}/{url}"), &tarball, "");
596-
if let Some(sha256) = checksum {
597-
if !self.verify(&tarball, sha256) {
598-
panic!("failed to verify {}", tarball.display());
599-
}
600-
}
601-
602-
self.unpack(&tarball, &bin_root, prefix);
603-
}
604-
}

src/bootstrap/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ mod format;
5555
mod install;
5656
mod llvm;
5757
mod metadata;
58-
mod render_tests;
5958
mod min_config;
59+
mod render_tests;
6060
mod run;
6161
mod sanity;
6262
mod setup;
@@ -91,8 +91,8 @@ use crate::cache::{Interned, INTERNER};
9191
pub use crate::config::Config;
9292
pub use crate::flags::Flags;
9393
pub use crate::flags::Subcommand;
94-
use termcolor::{ColorChoice, StandardStream, WriteColor};
9594
pub use crate::min_config::MinimalConfig;
95+
use termcolor::{ColorChoice, StandardStream, WriteColor};
9696

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

0 commit comments

Comments
 (0)