Skip to content

Commit 64187b8

Browse files
committed
Auto merge of rust-lang#92260 - jyn514:less-python-logic, r=Mark-Simulacrum
Move some more bootstrap logic from python to rust Same rationale as rust-lang#76544; it would be nice to make python entirely optional at some point. This also removes $ROOT as an option for the build directory; I haven't been using it, and like Alex said in rust-lang#76544 (comment) it seems like a misfeature. This allows running `cargo run` from src/bootstrap, although that still gives lots of compile errors if you don't use the beta toolchain. It's not exactly the same as using `x.py`, since it won't have `BOOTSTRAP_DOWNLOAD_RUSTC` set, but it's pretty close. Doing this from the top-level directory requires rust-lang/cargo#7290 to be fixed, or using `cargo run -p bootstrap`. The next steps for making python optional are to move download-ci-llvm and download-rustc support into rustbuild, likely be shelling out as the python scripts do today. It would also be nice (although not required) to move submodule support there, but that would require taking bootstrap out of the workspace to avoid errors from crates that haven't been cloned yet. r? `@Mark-Simulacrum`
2 parents b97dc20 + 477cae3 commit 64187b8

File tree

10 files changed

+171
-49
lines changed

10 files changed

+171
-49
lines changed

src/bootstrap/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name = "bootstrap"
33
version = "0.0.0"
44
edition = "2021"
55
build = "build.rs"
6+
default-run = "bootstrap"
67

78
[lib]
89
path = "lib.rs"

src/bootstrap/bootstrap.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -1267,7 +1267,7 @@ def bootstrap(help_triggered):
12671267
build.check_vendored_status()
12681268

12691269
build_dir = build.get_toml('build-dir', 'build') or 'build'
1270-
build.build_dir = os.path.abspath(build_dir.replace("$ROOT", build.rust_root))
1270+
build.build_dir = os.path.abspath(build_dir)
12711271

12721272
with open(os.path.join(build.rust_root, "src", "stage0.json")) as f:
12731273
data = json.load(f)
@@ -1302,10 +1302,7 @@ def bootstrap(help_triggered):
13021302
env = os.environ.copy()
13031303
env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
13041304
env["BOOTSTRAP_PYTHON"] = sys.executable
1305-
env["BUILD_DIR"] = build.build_dir
13061305
env["RUSTC_BOOTSTRAP"] = '1'
1307-
if toml_path:
1308-
env["BOOTSTRAP_CONFIG"] = toml_path
13091306
if build.rustc_commit is not None:
13101307
env["BOOTSTRAP_DOWNLOAD_RUSTC"] = '1'
13111308
run(args, env=env, verbose=build.verbose, is_bootstrap=True)

src/bootstrap/builder.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ impl<'a> Builder<'a> {
883883
}
884884

885885
pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command {
886-
let mut cmd = Command::new(&self.out.join("bootstrap/debug/rustdoc"));
886+
let mut cmd = Command::new(&self.bootstrap_out.join("rustdoc"));
887887
cmd.env("RUSTC_STAGE", compiler.stage.to_string())
888888
.env("RUSTC_SYSROOT", self.sysroot(compiler))
889889
// Note that this is *not* the sysroot_libdir because rustdoc must be linked
@@ -1249,7 +1249,7 @@ impl<'a> Builder<'a> {
12491249
.env("RUSTC_STAGE", stage.to_string())
12501250
.env("RUSTC_SYSROOT", &sysroot)
12511251
.env("RUSTC_LIBDIR", &libdir)
1252-
.env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
1252+
.env("RUSTDOC", self.bootstrap_out.join("rustdoc"))
12531253
.env(
12541254
"RUSTDOC_REAL",
12551255
if cmd == "doc" || cmd == "rustdoc" || (cmd == "test" && want_rustdoc) {
@@ -1263,7 +1263,7 @@ impl<'a> Builder<'a> {
12631263
// Clippy support is a hack and uses the default `cargo-clippy` in path.
12641264
// Don't override RUSTC so that the `cargo-clippy` in path will be run.
12651265
if cmd != "clippy" {
1266-
cargo.env("RUSTC", self.out.join("bootstrap/debug/rustc"));
1266+
cargo.env("RUSTC", self.bootstrap_out.join("rustc"));
12671267
}
12681268

12691269
// Dealing with rpath here is a little special, so let's go into some

src/bootstrap/builder/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
88
config.save_toolstates = None;
99
config.dry_run = true;
1010
config.ninja_in_file = false;
11-
// try to avoid spurious failures in dist where we create/delete each others file
1211
config.out = PathBuf::from(env::var_os("BOOTSTRAP_OUTPUT_DIRECTORY").unwrap());
1312
config.initial_rustc = PathBuf::from(env::var_os("RUSTC").unwrap());
1413
config.initial_cargo = PathBuf::from(env::var_os("BOOTSTRAP_INITIAL_CARGO").unwrap());
14+
// try to avoid spurious failures in dist where we create/delete each others file
1515
let dir = config
1616
.out
1717
.join("tmp-rustbuild-tests")

src/bootstrap/config.rs

+26-25
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use std::cmp;
77
use std::collections::{HashMap, HashSet};
88
use std::env;
9-
use std::ffi::OsString;
109
use std::fmt;
1110
use std::fs;
1211
use std::path::{Path, PathBuf};
@@ -392,7 +391,6 @@ derive_merge! {
392391
build: Option<String>,
393392
host: Option<Vec<String>>,
394393
target: Option<Vec<String>>,
395-
// This is ignored, the rust code always gets the build directory from the `BUILD_DIR` env variable
396394
build_dir: Option<String>,
397395
cargo: Option<String>,
398396
rustc: Option<String>,
@@ -588,18 +586,6 @@ derive_merge! {
588586
}
589587

590588
impl Config {
591-
fn path_from_python(var_key: &str) -> PathBuf {
592-
match env::var_os(var_key) {
593-
Some(var_val) => Self::normalize_python_path(var_val),
594-
_ => panic!("expected '{}' to be set", var_key),
595-
}
596-
}
597-
598-
/// Normalizes paths from Python slightly. We don't trust paths from Python (#49785).
599-
fn normalize_python_path(path: OsString) -> PathBuf {
600-
Path::new(&path).components().collect()
601-
}
602-
603589
pub fn default_opts() -> Config {
604590
let mut config = Config::default();
605591
config.llvm_optimize = true;
@@ -625,7 +611,7 @@ impl Config {
625611
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
626612
// Undo `src/bootstrap`
627613
config.src = manifest_dir.parent().unwrap().parent().unwrap().to_owned();
628-
config.out = Config::path_from_python("BUILD_DIR");
614+
config.out = PathBuf::from("build");
629615

630616
config.initial_cargo = PathBuf::from(env!("CARGO"));
631617
config.initial_rustc = PathBuf::from(env!("RUSTC"));
@@ -655,12 +641,6 @@ impl Config {
655641
config.llvm_profile_use = flags.llvm_profile_use;
656642
config.llvm_profile_generate = flags.llvm_profile_generate;
657643

658-
if config.dry_run {
659-
let dir = config.out.join("tmp-dry-run");
660-
t!(fs::create_dir_all(&dir));
661-
config.out = dir;
662-
}
663-
664644
#[cfg(test)]
665645
let get_toml = |_| TomlConfig::default();
666646
#[cfg(not(test))]
@@ -677,7 +657,15 @@ impl Config {
677657
}
678658
};
679659

680-
let mut toml = flags.config.as_deref().map(get_toml).unwrap_or_else(TomlConfig::default);
660+
// check --config first, then `$RUST_BOOTSTRAP_CONFIG` first, then `config.toml`
661+
let toml_path = flags
662+
.config
663+
.clone()
664+
.or_else(|| env::var_os("RUST_BOOTSTRAP_CONFIG").map(PathBuf::from))
665+
.unwrap_or_else(|| PathBuf::from("config.toml"));
666+
let mut toml =
667+
if toml_path.exists() { get_toml(&toml_path) } else { TomlConfig::default() };
668+
681669
if let Some(include) = &toml.profile {
682670
let mut include_path = config.src.clone();
683671
include_path.push("src");
@@ -689,12 +677,25 @@ impl Config {
689677
}
690678

691679
config.changelog_seen = toml.changelog_seen;
692-
if let Some(cfg) = flags.config {
693-
config.config = cfg;
694-
}
680+
config.config = toml_path;
695681

696682
let build = toml.build.unwrap_or_default();
697683

684+
set(&mut config.initial_rustc, build.rustc.map(PathBuf::from));
685+
set(&mut config.out, build.build_dir.map(PathBuf::from));
686+
// NOTE: Bootstrap spawns various commands with different working directories.
687+
// To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
688+
if !config.out.is_absolute() {
689+
// `canonicalize` requires the path to already exist. Use our vendored copy of `absolute` instead.
690+
config.out = crate::util::absolute(&config.out);
691+
}
692+
693+
if config.dry_run {
694+
let dir = config.out.join("tmp-dry-run");
695+
t!(fs::create_dir_all(&dir));
696+
config.out = dir;
697+
}
698+
698699
config.hosts = if let Some(arg_host) = flags.host {
699700
arg_host
700701
} else if let Some(file_host) = build.host {

src/bootstrap/flags.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! This module implements the command-line parsing of the build system which
44
//! has various flags to configure how it's run.
55
6-
use std::env;
76
use std::path::PathBuf;
87
use std::process;
98

@@ -541,7 +540,6 @@ Arguments:
541540
// Get any optional paths which occur after the subcommand
542541
let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
543542

544-
let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
545543
let verbose = matches.opt_present("verbose");
546544

547545
// User passed in -h/--help?
@@ -671,7 +669,7 @@ Arguments:
671669
} else {
672670
None
673671
},
674-
config: cfg_file,
672+
config: matches.opt_str("config").map(PathBuf::from),
675673
jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")),
676674
cmd,
677675
incremental: matches.opt_present("incremental"),

src/bootstrap/lib.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ pub struct Build {
261261
// Properties derived from the above configuration
262262
src: PathBuf,
263263
out: PathBuf,
264+
bootstrap_out: PathBuf,
264265
rust_info: channel::GitInfo,
265266
cargo_info: channel::GitInfo,
266267
rls_info: channel::GitInfo,
@@ -435,6 +436,20 @@ impl Build {
435436
.expect("failed to read src/version");
436437
let version = version.trim();
437438

439+
let bootstrap_out = if std::env::var("BOOTSTRAP_PYTHON").is_ok() {
440+
out.join("bootstrap").join("debug")
441+
} else {
442+
let workspace_target_dir = std::env::var("CARGO_TARGET_DIR")
443+
.map(PathBuf::from)
444+
.unwrap_or_else(|_| src.join("target"));
445+
let bootstrap_out = workspace_target_dir.join("debug");
446+
if !bootstrap_out.join("rustc").exists() {
447+
// this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented
448+
panic!("run `cargo build --bins` before `cargo run`")
449+
}
450+
bootstrap_out
451+
};
452+
438453
let mut build = Build {
439454
initial_rustc: config.initial_rustc.clone(),
440455
initial_cargo: config.initial_cargo.clone(),
@@ -453,6 +468,7 @@ impl Build {
453468
version: version.to_string(),
454469
src,
455470
out,
471+
bootstrap_out,
456472

457473
rust_info,
458474
cargo_info,
@@ -629,7 +645,7 @@ impl Build {
629645
}
630646

631647
if let Subcommand::Setup { profile } = &self.config.cmd {
632-
return setup::setup(&self.config.src, *profile);
648+
return setup::setup(&self.config, *profile);
633649
}
634650

635651
{

src/bootstrap/setup.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::TargetSelection;
21
use crate::{t, VERSION};
2+
use crate::{Config, TargetSelection};
33
use std::env::consts::EXE_SUFFIX;
44
use std::fmt::Write as _;
55
use std::fs::File;
@@ -81,24 +81,22 @@ impl fmt::Display for Profile {
8181
}
8282
}
8383

84-
pub fn setup(src_path: &Path, profile: Profile) {
85-
let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
84+
pub fn setup(config: &Config, profile: Profile) {
85+
let path = &config.config;
8686

87-
if cfg_file.as_ref().map_or(false, |f| f.exists()) {
88-
let file = cfg_file.unwrap();
87+
if path.exists() {
8988
println!(
9089
"error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
91-
file.display()
90+
path.display()
9291
);
93-
println!("help: try adding `profile = \"{}\"` at the top of {}", profile, file.display());
92+
println!("help: try adding `profile = \"{}\"` at the top of {}", profile, path.display());
9493
println!(
9594
"note: this will use the configuration in {}",
96-
profile.include_path(src_path).display()
95+
profile.include_path(&config.src).display()
9796
);
9897
std::process::exit(1);
9998
}
10099

101-
let path = cfg_file.unwrap_or_else(|| "config.toml".into());
102100
let settings = format!(
103101
"# Includes one of the default files in src/bootstrap/defaults\n\
104102
profile = \"{}\"\n\
@@ -107,7 +105,7 @@ pub fn setup(src_path: &Path, profile: Profile) {
107105
);
108106
t!(fs::write(path, settings));
109107

110-
let include_path = profile.include_path(src_path);
108+
let include_path = profile.include_path(&config.src);
111109
println!("`x.py` will now use the configuration at {}", include_path.display());
112110

113111
let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
@@ -138,7 +136,7 @@ pub fn setup(src_path: &Path, profile: Profile) {
138136

139137
println!();
140138

141-
t!(install_git_hook_maybe(src_path));
139+
t!(install_git_hook_maybe(&config.src));
142140

143141
println!();
144142

src/bootstrap/test.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ impl Step for RustdocTheme {
730730
}
731731

732732
fn run(self, builder: &Builder<'_>) {
733-
let rustdoc = builder.out.join("bootstrap/debug/rustdoc");
733+
let rustdoc = builder.bootstrap_out.join("rustdoc");
734734
let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
735735
cmd.arg(rustdoc.to_str().unwrap())
736736
.arg(builder.src.join("src/librustdoc/html/static/css/themes").to_str().unwrap())
@@ -2346,6 +2346,8 @@ impl Step for Bootstrap {
23462346
.current_dir(builder.src.join("src/bootstrap"))
23472347
.env("RUSTFLAGS", "-Cdebuginfo=2")
23482348
.env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
2349+
// HACK: bootstrap's tests want to know the output directory, but there's no way to set
2350+
// it except through config.toml. Set it through an env variable instead.
23492351
.env("BOOTSTRAP_OUTPUT_DIRECTORY", &builder.config.out)
23502352
.env("BOOTSTRAP_INITIAL_CARGO", &builder.config.initial_cargo)
23512353
.env("RUSTC_BOOTSTRAP", "1")

0 commit comments

Comments
 (0)