Skip to content

Commit 645bc60

Browse files
committed
Auto merge of #124883 - onur-ozkan:change-stage0-file, r=Mark-Simulacrum
use key-value format in stage0 file Currently, we are working on the python removal task on bootstrap. Which means we have to extract some data from the stage0 file using shell scripts. However, parsing values from the stage0.json file is painful because shell scripts don't have a built-in way to parse json files. This change simplifies the stage0 file format to key-value pairs, which makes it easily readable from any environment. See the zulip thread for more details: https://rust-lang.zulipchat.com/#narrow/stream/326414-t-infra.2Fbootstrap/topic/Using.20different.20format.20in.20the.20stage0.20file
2 parents 8cc6f34 + 8c5375a commit 645bc60

File tree

13 files changed

+635
-590
lines changed

13 files changed

+635
-590
lines changed

.github/workflows/dependencies.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
- name: install the bootstrap toolchain
5757
run: |
5858
# Extract the stage0 version
59-
TOOLCHAIN=$(jq -r '.compiler | {version,date} | join("-")' -- src/stage0.json)
59+
TOOLCHAIN=$(awk -F= '{a[$1]=$2} END {print(a["compiler_version"] "-" a["compiler_date"])}' src/stage0)
6060
# Install and set as default
6161
rustup toolchain install --no-self-update --profile minimal $TOOLCHAIN
6262
rustup default $TOOLCHAIN

Cargo.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,10 +381,10 @@ name = "bump-stage0"
381381
version = "0.1.0"
382382
dependencies = [
383383
"anyhow",
384+
"build_helper",
384385
"curl",
385386
"indexmap",
386387
"serde",
387-
"serde_json",
388388
"toml 0.5.11",
389389
]
390390

config.example.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -213,17 +213,17 @@
213213
# the root of the repository.
214214
#build-dir = "build"
215215

216-
# Instead of downloading the src/stage0.json version of Cargo specified, use
216+
# Instead of downloading the src/stage0 version of Cargo specified, use
217217
# this Cargo binary instead to build all Rust code
218218
# If you set this, you likely want to set `rustc` as well.
219219
#cargo = "/path/to/cargo"
220220

221-
# Instead of downloading the src/stage0.json version of the compiler
221+
# Instead of downloading the src/stage0 version of the compiler
222222
# specified, use this rustc binary instead as the stage0 snapshot compiler.
223223
# If you set this, you likely want to set `cargo` as well.
224224
#rustc = "/path/to/rustc"
225225

226-
# Instead of downloading the src/stage0.json version of rustfmt specified,
226+
# Instead of downloading the src/stage0 version of rustfmt specified,
227227
# use this rustfmt binary instead as the stage0 snapshot rustfmt.
228228
#rustfmt = "/path/to/rustfmt"
229229

src/bootstrap/bootstrap.py

+24-14
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import contextlib
44
import datetime
55
import hashlib
6-
import json
76
import os
87
import re
98
import shutil
@@ -52,7 +51,7 @@ def get(base, url, path, checksums, verbose=False):
5251

5352
try:
5453
if url not in checksums:
55-
raise RuntimeError(("src/stage0.json doesn't contain a checksum for {}. "
54+
raise RuntimeError(("src/stage0 doesn't contain a checksum for {}. "
5655
"Pre-built artifacts might not be available for this "
5756
"target at this time, see https://doc.rust-lang.org/nightly"
5857
"/rustc/platform-support.html for more information.")
@@ -421,9 +420,9 @@ def output(filepath):
421420

422421

423422
class Stage0Toolchain:
424-
def __init__(self, stage0_payload):
425-
self.date = stage0_payload["date"]
426-
self.version = stage0_payload["version"]
423+
def __init__(self, date, version):
424+
self.date = date
425+
self.version = version
427426

428427
def channel(self):
429428
return self.version + "-" + self.date
@@ -439,7 +438,7 @@ def __init__(
439438
bin_root,
440439
tarball_path,
441440
tarball_suffix,
442-
checksums_sha256,
441+
stage0_data,
443442
pattern,
444443
verbose,
445444
):
@@ -448,7 +447,7 @@ def __init__(
448447
self.bin_root = bin_root
449448
self.tarball_path = tarball_path
450449
self.tarball_suffix = tarball_suffix
451-
self.checksums_sha256 = checksums_sha256
450+
self.stage0_data = stage0_data
452451
self.pattern = pattern
453452
self.verbose = verbose
454453

@@ -458,7 +457,7 @@ def download_component(download_info):
458457
download_info.base_download_url,
459458
download_info.download_path,
460459
download_info.tarball_path,
461-
download_info.checksums_sha256,
460+
download_info.stage0_data,
462461
verbose=download_info.verbose,
463462
)
464463

@@ -510,11 +509,12 @@ def __init__(self, config_toml="", args=None):
510509
build_dir = args.build_dir or self.get_toml('build-dir', 'build') or 'build'
511510
self.build_dir = os.path.abspath(build_dir)
512511

513-
with open(os.path.join(self.rust_root, "src", "stage0.json")) as f:
514-
data = json.load(f)
515-
self.checksums_sha256 = data["checksums_sha256"]
516-
self.stage0_compiler = Stage0Toolchain(data["compiler"])
517-
self.download_url = os.getenv("RUSTUP_DIST_SERVER") or data["config"]["dist_server"]
512+
self.stage0_data = parse_stage0_file(os.path.join(self.rust_root, "src", "stage0"))
513+
self.stage0_compiler = Stage0Toolchain(
514+
self.stage0_data["compiler_date"],
515+
self.stage0_data["compiler_version"]
516+
)
517+
self.download_url = os.getenv("RUSTUP_DIST_SERVER") or self.stage0_data["dist_server"]
518518

519519
self.build = args.build or self.build_triple()
520520

@@ -581,7 +581,7 @@ def download_toolchain(self):
581581
bin_root=self.bin_root(),
582582
tarball_path=os.path.join(rustc_cache, filename),
583583
tarball_suffix=tarball_suffix,
584-
checksums_sha256=self.checksums_sha256,
584+
stage0_data=self.stage0_data,
585585
pattern=pattern,
586586
verbose=self.verbose,
587587
)
@@ -1071,6 +1071,16 @@ def parse_args(args):
10711071

10721072
return parser.parse_known_args(args)[0]
10731073

1074+
def parse_stage0_file(path):
1075+
result = {}
1076+
with open(path, 'r') as file:
1077+
for line in file:
1078+
line = line.strip()
1079+
if line and not line.startswith('#'):
1080+
key, value = line.split('=', 1)
1081+
result[key.strip()] = value.strip()
1082+
return result
1083+
10741084
def bootstrap(args):
10751085
"""Configure, fetch, build and run the initial bootstrap"""
10761086
rust_root = os.path.abspath(os.path.join(__file__, '../../..'))

src/bootstrap/src/core/config/config.rs

+4-34
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ pub struct Config {
181181
pub test_compare_mode: bool,
182182
pub color: Color,
183183
pub patch_binaries_for_nix: Option<bool>,
184-
pub stage0_metadata: Stage0Metadata,
184+
pub stage0_metadata: build_helper::stage0_parser::Stage0,
185185
pub android_ndk: Option<PathBuf>,
186186
/// Whether to use the `c` feature of the `compiler_builtins` crate.
187187
pub optimized_compiler_builtins: bool,
@@ -351,34 +351,6 @@ pub struct Config {
351351
pub paths: Vec<PathBuf>,
352352
}
353353

354-
#[derive(Default, Deserialize, Clone)]
355-
pub struct Stage0Metadata {
356-
pub compiler: CompilerMetadata,
357-
pub config: Stage0Config,
358-
pub checksums_sha256: HashMap<String, String>,
359-
pub rustfmt: Option<RustfmtMetadata>,
360-
}
361-
#[derive(Default, Deserialize, Clone)]
362-
pub struct CompilerMetadata {
363-
pub date: String,
364-
pub version: String,
365-
}
366-
367-
#[derive(Default, Deserialize, Clone)]
368-
pub struct Stage0Config {
369-
pub dist_server: String,
370-
pub artifacts_server: String,
371-
pub artifacts_with_llvm_assertions_server: String,
372-
pub git_merge_commit_email: String,
373-
pub git_repository: String,
374-
pub nightly_branch: String,
375-
}
376-
#[derive(Default, Deserialize, Clone)]
377-
pub struct RustfmtMetadata {
378-
pub date: String,
379-
pub version: String,
380-
}
381-
382354
#[derive(Clone, Debug, Default)]
383355
pub enum RustfmtState {
384356
SystemToolchain(PathBuf),
@@ -1298,13 +1270,13 @@ impl Config {
12981270
Some(p) => PathBuf::from(p),
12991271
None => git_root,
13001272
};
1301-
// If this doesn't have at least `stage0.json`, we guessed wrong. This can happen when,
1273+
// If this doesn't have at least `stage0`, we guessed wrong. This can happen when,
13021274
// for example, the build directory is inside of another unrelated git directory.
13031275
// In that case keep the original `CARGO_MANIFEST_DIR` handling.
13041276
//
13051277
// NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside
13061278
// the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.
1307-
if git_root.join("src").join("stage0.json").exists() {
1279+
if git_root.join("src").join("stage0").exists() {
13081280
config.src = git_root;
13091281
}
13101282
} else {
@@ -1322,9 +1294,7 @@ impl Config {
13221294
.to_path_buf();
13231295
}
13241296

1325-
let stage0_json = t!(std::fs::read(config.src.join("src").join("stage0.json")));
1326-
1327-
config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json));
1297+
config.stage0_metadata = build_helper::stage0_parser::parse_stage0_file();
13281298

13291299
// Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, then `config.toml` in the root directory.
13301300
let toml_path = flags

src/bootstrap/src/core/download.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use std::{
99
};
1010

1111
use build_helper::ci::CiEnv;
12+
use build_helper::stage0_parser::VersionMetadata;
1213
use xz2::bufread::XzDecoder;
1314

14-
use crate::core::config::RustfmtMetadata;
1515
use crate::utils::helpers::{check_run, exe, program_out_of_date};
1616
use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
1717
use crate::{t, Config};
@@ -408,7 +408,7 @@ impl Config {
408408
/// NOTE: rustfmt is a completely different toolchain than the bootstrap compiler, so it can't
409409
/// reuse target directories or artifacts
410410
pub(crate) fn maybe_download_rustfmt(&self) -> Option<PathBuf> {
411-
let RustfmtMetadata { date, version } = self.stage0_metadata.rustfmt.as_ref()?;
411+
let VersionMetadata { date, version } = self.stage0_metadata.rustfmt.as_ref()?;
412412
let channel = format!("{version}-{date}");
413413

414414
let host = self.build;
@@ -606,7 +606,7 @@ impl Config {
606606
DownloadSource::Dist => {
607607
let dist_server = env::var("RUSTUP_DIST_SERVER")
608608
.unwrap_or(self.stage0_metadata.config.dist_server.to_string());
609-
// NOTE: make `dist` part of the URL because that's how it's stored in src/stage0.json
609+
// NOTE: make `dist` part of the URL because that's how it's stored in src/stage0
610610
(dist_server, format!("dist/{key}/{filename}"), true)
611611
}
612612
};
@@ -616,7 +616,7 @@ impl Config {
616616
// this on each and every nightly ...
617617
let checksum = if should_verify {
618618
let error = format!(
619-
"src/stage0.json doesn't contain a checksum for {url}. \
619+
"src/stage0 doesn't contain a checksum for {url}. \
620620
Pre-built artifacts might not be available for this \
621621
target at this time, see https://doc.rust-lang.org/nightly\
622622
/rustc/platform-support.html for more information."

0 commit comments

Comments
 (0)