mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
Auto merge of #127680 - Kobzol:bootstrap-cmd-refactor-6, r=onur-ozkan
Bootstrap command refactoring: port remaining commands with access to `Build` (step 6) Continuation of https://github.com/rust-lang/rust/pull/127450. This PR ports commands in bootstrap that can easily get access to `Build(er)` to `BootstrapCommand`. After this PR, everything that can access `Build(er)` should be using the new API. Statistics of `bootstrap` code (ignoring `src/bin/<shims>`) after this PR: ``` 7 usages of `Command::new` 69 usages of `command()` (new API) - out of that: 16 usages of `as_command_mut()` (new API, but accesses the inner command) ``` Tracking issue: https://github.com/rust-lang/rust/issues/126819 r? `@onur-ozkan`
This commit is contained in:
commit
2823cfb1e5
@ -14,7 +14,7 @@ use std::fs;
|
|||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::Stdio;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
@ -695,10 +695,10 @@ fn copy_sanitizers(
|
|||||||
|| target == "x86_64-apple-ios"
|
|| target == "x86_64-apple-ios"
|
||||||
{
|
{
|
||||||
// Update the library’s install name to reflect that it has been renamed.
|
// Update the library’s install name to reflect that it has been renamed.
|
||||||
apple_darwin_update_library_name(&dst, &format!("@rpath/{}", &runtime.name));
|
apple_darwin_update_library_name(builder, &dst, &format!("@rpath/{}", &runtime.name));
|
||||||
// Upon renaming the install name, the code signature of the file will invalidate,
|
// Upon renaming the install name, the code signature of the file will invalidate,
|
||||||
// so we will sign it again.
|
// so we will sign it again.
|
||||||
apple_darwin_sign_file(&dst);
|
apple_darwin_sign_file(builder, &dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
target_deps.push(dst);
|
target_deps.push(dst);
|
||||||
@ -707,25 +707,17 @@ fn copy_sanitizers(
|
|||||||
target_deps
|
target_deps
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apple_darwin_update_library_name(library_path: &Path, new_name: &str) {
|
fn apple_darwin_update_library_name(builder: &Builder<'_>, library_path: &Path, new_name: &str) {
|
||||||
let status = Command::new("install_name_tool")
|
command("install_name_tool").arg("-id").arg(new_name).arg(library_path).run(builder);
|
||||||
.arg("-id")
|
|
||||||
.arg(new_name)
|
|
||||||
.arg(library_path)
|
|
||||||
.status()
|
|
||||||
.expect("failed to execute `install_name_tool`");
|
|
||||||
assert!(status.success());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apple_darwin_sign_file(file_path: &Path) {
|
fn apple_darwin_sign_file(builder: &Builder<'_>, file_path: &Path) {
|
||||||
let status = Command::new("codesign")
|
command("codesign")
|
||||||
.arg("-f") // Force to rewrite the existing signature
|
.arg("-f") // Force to rewrite the existing signature
|
||||||
.arg("-s")
|
.arg("-s")
|
||||||
.arg("-")
|
.arg("-")
|
||||||
.arg(file_path)
|
.arg(file_path)
|
||||||
.status()
|
.run(builder);
|
||||||
.expect("failed to execute `codesign`");
|
|
||||||
assert!(status.success());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
@ -1171,7 +1163,7 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
|
|||||||
if builder.config.llvm_profile_generate && target.is_msvc() {
|
if builder.config.llvm_profile_generate && target.is_msvc() {
|
||||||
if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
|
if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
|
||||||
// Add clang's runtime library directory to the search path
|
// Add clang's runtime library directory to the search path
|
||||||
let clang_rt_dir = get_clang_cl_resource_dir(clang_cl_path);
|
let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
|
||||||
llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
|
llvm_linker_flags.push_str(&format!("-L{}", clang_rt_dir.display()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,7 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L
|
|||||||
static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
|
static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
|
||||||
let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
|
let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
|
||||||
generate_smart_stamp_hash(
|
generate_smart_stamp_hash(
|
||||||
|
builder,
|
||||||
&builder.config.src.join("src/llvm-project"),
|
&builder.config.src.join("src/llvm-project"),
|
||||||
builder.in_tree_llvm_info.sha().unwrap_or_default(),
|
builder.in_tree_llvm_info.sha().unwrap_or_default(),
|
||||||
)
|
)
|
||||||
@ -912,7 +913,7 @@ impl Step for Lld {
|
|||||||
if let Some(clang_cl_path) = builder.config.llvm_clang_cl.as_ref() {
|
if let Some(clang_cl_path) = builder.config.llvm_clang_cl.as_ref() {
|
||||||
// Find clang's runtime library directory and push that as a search path to the
|
// Find clang's runtime library directory and push that as a search path to the
|
||||||
// cmake linker flags.
|
// cmake linker flags.
|
||||||
let clang_rt_dir = get_clang_cl_resource_dir(clang_cl_path);
|
let clang_rt_dir = get_clang_cl_resource_dir(builder, clang_cl_path);
|
||||||
ldflags.push_all(format!("/libpath:{}", clang_rt_dir.display()));
|
ldflags.push_all(format!("/libpath:{}", clang_rt_dir.display()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
|
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||||
use crate::t;
|
use crate::t;
|
||||||
use crate::utils::change_tracker::CONFIG_CHANGE_HISTORY;
|
use crate::utils::change_tracker::CONFIG_CHANGE_HISTORY;
|
||||||
|
use crate::utils::exec::command;
|
||||||
use crate::utils::helpers::{self, hex_encode};
|
use crate::utils::helpers::{self, hex_encode};
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
@ -16,7 +17,6 @@ use std::fmt::Write as _;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::{Path, PathBuf, MAIN_SEPARATOR_STR};
|
use std::path::{Path, PathBuf, MAIN_SEPARATOR_STR};
|
||||||
use std::process::Command;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{fmt, fs, io};
|
use std::{fmt, fs, io};
|
||||||
|
|
||||||
@ -266,20 +266,16 @@ impl Step for Link {
|
|||||||
}
|
}
|
||||||
let stage_path =
|
let stage_path =
|
||||||
["build", config.build.rustc_target_arg(), "stage1"].join(MAIN_SEPARATOR_STR);
|
["build", config.build.rustc_target_arg(), "stage1"].join(MAIN_SEPARATOR_STR);
|
||||||
if !rustup_installed() {
|
if !rustup_installed(builder) {
|
||||||
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
|
eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
|
||||||
} else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
|
} else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
|
||||||
attempt_toolchain_link(&stage_path[..]);
|
attempt_toolchain_link(builder, &stage_path[..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rustup_installed() -> bool {
|
fn rustup_installed(builder: &Builder<'_>) -> bool {
|
||||||
Command::new("rustup")
|
command("rustup").capture_stdout().arg("--version").run(builder).is_success()
|
||||||
.arg("--version")
|
|
||||||
.stdout(std::process::Stdio::null())
|
|
||||||
.output()
|
|
||||||
.map_or(false, |output| output.status.success())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stage_dir_exists(stage_path: &str) -> bool {
|
fn stage_dir_exists(stage_path: &str) -> bool {
|
||||||
@ -289,8 +285,8 @@ fn stage_dir_exists(stage_path: &str) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attempt_toolchain_link(stage_path: &str) {
|
fn attempt_toolchain_link(builder: &Builder<'_>, stage_path: &str) {
|
||||||
if toolchain_is_linked() {
|
if toolchain_is_linked(builder) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +297,7 @@ fn attempt_toolchain_link(stage_path: &str) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if try_link_toolchain(stage_path) {
|
if try_link_toolchain(builder, stage_path) {
|
||||||
println!(
|
println!(
|
||||||
"Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
|
"Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
|
||||||
);
|
);
|
||||||
@ -315,14 +311,16 @@ fn attempt_toolchain_link(stage_path: &str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toolchain_is_linked() -> bool {
|
fn toolchain_is_linked(builder: &Builder<'_>) -> bool {
|
||||||
match Command::new("rustup")
|
match command("rustup")
|
||||||
|
.capture_stdout()
|
||||||
|
.allow_failure()
|
||||||
.args(["toolchain", "list"])
|
.args(["toolchain", "list"])
|
||||||
.stdout(std::process::Stdio::piped())
|
.run(builder)
|
||||||
.output()
|
.stdout_if_ok()
|
||||||
{
|
{
|
||||||
Ok(toolchain_list) => {
|
Some(toolchain_list) => {
|
||||||
if !String::from_utf8_lossy(&toolchain_list.stdout).contains("stage1") {
|
if !toolchain_list.contains("stage1") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// The toolchain has already been linked.
|
// The toolchain has already been linked.
|
||||||
@ -330,7 +328,7 @@ fn toolchain_is_linked() -> bool {
|
|||||||
"`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
|
"`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
None => {
|
||||||
// In this case, we don't know if the `stage1` toolchain has been linked;
|
// In this case, we don't know if the `stage1` toolchain has been linked;
|
||||||
// but `rustup` failed, so let's not go any further.
|
// but `rustup` failed, so let's not go any further.
|
||||||
println!(
|
println!(
|
||||||
@ -341,12 +339,12 @@ fn toolchain_is_linked() -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_link_toolchain(stage_path: &str) -> bool {
|
fn try_link_toolchain(builder: &Builder<'_>, stage_path: &str) -> bool {
|
||||||
Command::new("rustup")
|
command("rustup")
|
||||||
.stdout(std::process::Stdio::null())
|
.capture_stdout()
|
||||||
.args(["toolchain", "link", "stage1", stage_path])
|
.args(["toolchain", "link", "stage1", stage_path])
|
||||||
.output()
|
.run(builder)
|
||||||
.map_or(false, |output| output.status.success())
|
.is_success()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_stage1_toolchain_placeholder_exists(stage_path: &str) -> bool {
|
fn ensure_stage1_toolchain_placeholder_exists(stage_path: &str) -> bool {
|
||||||
@ -476,20 +474,18 @@ impl Step for Hook {
|
|||||||
if config.dry_run() {
|
if config.dry_run() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t!(install_git_hook_maybe(config));
|
t!(install_git_hook_maybe(builder, config));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// install a git hook to automatically run tidy, if they want
|
// install a git hook to automatically run tidy, if they want
|
||||||
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
|
fn install_git_hook_maybe(builder: &Builder<'_>, config: &Config) -> io::Result<()> {
|
||||||
let git = helpers::git(Some(&config.src))
|
let git = helpers::git(Some(&config.src))
|
||||||
|
.capture()
|
||||||
.args(["rev-parse", "--git-common-dir"])
|
.args(["rev-parse", "--git-common-dir"])
|
||||||
.as_command_mut()
|
.run(builder)
|
||||||
.output()
|
.stdout();
|
||||||
.map(|output| {
|
let git = PathBuf::from(git.trim());
|
||||||
assert!(output.status.success(), "failed to run `git`");
|
|
||||||
PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
|
|
||||||
})?;
|
|
||||||
let hooks_dir = git.join("hooks");
|
let hooks_dir = git.join("hooks");
|
||||||
let dst = hooks_dir.join("pre-push");
|
let dst = hooks_dir.join("pre-push");
|
||||||
if dst.exists() {
|
if dst.exists() {
|
||||||
|
@ -9,7 +9,6 @@ use std::ffi::OsString;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Stdio};
|
|
||||||
|
|
||||||
use clap_complete::shells;
|
use clap_complete::shells;
|
||||||
|
|
||||||
@ -169,12 +168,8 @@ You can skip linkcheck with --skip src/tools/linkchecker"
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_if_tidy_is_installed() -> bool {
|
fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
|
||||||
Command::new("tidy")
|
command("tidy").capture_stdout().allow_failure().arg("--version").run(builder).is_success()
|
||||||
.arg("--version")
|
|
||||||
.stdout(Stdio::null())
|
|
||||||
.status()
|
|
||||||
.map_or(false, |status| status.success())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
@ -188,8 +183,9 @@ impl Step for HtmlCheck {
|
|||||||
const ONLY_HOSTS: bool = true;
|
const ONLY_HOSTS: bool = true;
|
||||||
|
|
||||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||||
|
let builder = run.builder;
|
||||||
let run = run.path("src/tools/html-checker");
|
let run = run.path("src/tools/html-checker");
|
||||||
run.lazy_default_condition(Box::new(check_if_tidy_is_installed))
|
run.lazy_default_condition(Box::new(|| check_if_tidy_is_installed(builder)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_run(run: RunConfig<'_>) {
|
fn make_run(run: RunConfig<'_>) {
|
||||||
@ -197,7 +193,7 @@ impl Step for HtmlCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(self, builder: &Builder<'_>) {
|
fn run(self, builder: &Builder<'_>) {
|
||||||
if !check_if_tidy_is_installed() {
|
if !check_if_tidy_is_installed(builder) {
|
||||||
eprintln!("not running HTML-check tool because `tidy` is missing");
|
eprintln!("not running HTML-check tool because `tidy` is missing");
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"You need the HTML tidy tool https://www.html-tidy.org/, this tool is *not* part of the rust project and needs to be installed separately, for example via your package manager."
|
"You need the HTML tidy tool https://www.html-tidy.org/, this tool is *not* part of the rust project and needs to be installed separately, for example via your package manager."
|
||||||
@ -2099,9 +2095,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
|
|||||||
let git_config = builder.config.git_config();
|
let git_config = builder.config.git_config();
|
||||||
cmd.arg("--git-repository").arg(git_config.git_repository);
|
cmd.arg("--git-repository").arg(git_config.git_repository);
|
||||||
cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
|
cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
|
||||||
|
cmd.force_coloring_in_ci(builder.ci_env);
|
||||||
// FIXME: Move CiEnv back to bootstrap, it is only used here anyway
|
|
||||||
builder.ci_env.force_coloring_in_ci(cmd.as_command_mut());
|
|
||||||
|
|
||||||
#[cfg(feature = "build-metrics")]
|
#[cfg(feature = "build-metrics")]
|
||||||
builder.metrics.begin_test_suite(
|
builder.metrics.begin_test_suite(
|
||||||
|
@ -99,24 +99,16 @@ fn print_error(tool: &str, submodule: &str) {
|
|||||||
crate::exit!(3);
|
crate::exit!(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_changed_files(toolstates: &HashMap<Box<str>, ToolState>) {
|
fn check_changed_files(builder: &Builder<'_>, toolstates: &HashMap<Box<str>, ToolState>) {
|
||||||
// Changed files
|
// Changed files
|
||||||
let output = helpers::git(None)
|
let output = helpers::git(None)
|
||||||
|
.capture()
|
||||||
.arg("diff")
|
.arg("diff")
|
||||||
.arg("--name-status")
|
.arg("--name-status")
|
||||||
.arg("HEAD")
|
.arg("HEAD")
|
||||||
.arg("HEAD^")
|
.arg("HEAD^")
|
||||||
.as_command_mut()
|
.run(builder)
|
||||||
.output();
|
.stdout();
|
||||||
let output = match output {
|
|
||||||
Ok(o) => o,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Failed to get changed files: {e:?}");
|
|
||||||
crate::exit!(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let output = t!(String::from_utf8(output.stdout));
|
|
||||||
|
|
||||||
for (tool, submodule) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) {
|
for (tool, submodule) in STABLE_TOOLS.iter().chain(NIGHTLY_TOOLS.iter()) {
|
||||||
let changed = output.lines().any(|l| l.starts_with('M') && l.ends_with(submodule));
|
let changed = output.lines().any(|l| l.starts_with('M') && l.ends_with(submodule));
|
||||||
@ -186,8 +178,8 @@ impl Step for ToolStateCheck {
|
|||||||
crate::exit!(1);
|
crate::exit!(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_changed_files(&toolstates);
|
check_changed_files(builder, &toolstates);
|
||||||
checkout_toolstate_repo();
|
checkout_toolstate_repo(builder);
|
||||||
let old_toolstate = read_old_toolstate();
|
let old_toolstate = read_old_toolstate();
|
||||||
|
|
||||||
for (tool, _) in STABLE_TOOLS.iter() {
|
for (tool, _) in STABLE_TOOLS.iter() {
|
||||||
@ -231,7 +223,7 @@ impl Step for ToolStateCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() {
|
if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() {
|
||||||
commit_toolstate_change(&toolstates);
|
commit_toolstate_change(builder, &toolstates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,55 +307,34 @@ fn toolstate_repo() -> String {
|
|||||||
const TOOLSTATE_DIR: &str = "rust-toolstate";
|
const TOOLSTATE_DIR: &str = "rust-toolstate";
|
||||||
|
|
||||||
/// Checks out the toolstate repo into `TOOLSTATE_DIR`.
|
/// Checks out the toolstate repo into `TOOLSTATE_DIR`.
|
||||||
fn checkout_toolstate_repo() {
|
fn checkout_toolstate_repo(builder: &Builder<'_>) {
|
||||||
if let Ok(token) = env::var("TOOLSTATE_REPO_ACCESS_TOKEN") {
|
if let Ok(token) = env::var("TOOLSTATE_REPO_ACCESS_TOKEN") {
|
||||||
prepare_toolstate_config(&token);
|
prepare_toolstate_config(builder, &token);
|
||||||
}
|
}
|
||||||
if Path::new(TOOLSTATE_DIR).exists() {
|
if Path::new(TOOLSTATE_DIR).exists() {
|
||||||
eprintln!("Cleaning old toolstate directory...");
|
eprintln!("Cleaning old toolstate directory...");
|
||||||
t!(fs::remove_dir_all(TOOLSTATE_DIR));
|
t!(fs::remove_dir_all(TOOLSTATE_DIR));
|
||||||
}
|
}
|
||||||
|
|
||||||
let status = helpers::git(None)
|
helpers::git(None)
|
||||||
.arg("clone")
|
.arg("clone")
|
||||||
.arg("--depth=1")
|
.arg("--depth=1")
|
||||||
.arg(toolstate_repo())
|
.arg(toolstate_repo())
|
||||||
.arg(TOOLSTATE_DIR)
|
.arg(TOOLSTATE_DIR)
|
||||||
.as_command_mut()
|
.run(builder);
|
||||||
.status();
|
|
||||||
let success = match status {
|
|
||||||
Ok(s) => s.success(),
|
|
||||||
Err(_) => false,
|
|
||||||
};
|
|
||||||
if !success {
|
|
||||||
panic!("git clone unsuccessful (status: {status:?})");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets up config and authentication for modifying the toolstate repo.
|
/// Sets up config and authentication for modifying the toolstate repo.
|
||||||
fn prepare_toolstate_config(token: &str) {
|
fn prepare_toolstate_config(builder: &Builder<'_>, token: &str) {
|
||||||
fn git_config(key: &str, value: &str) {
|
fn git_config(builder: &Builder<'_>, key: &str, value: &str) {
|
||||||
let status = helpers::git(None)
|
helpers::git(None).arg("config").arg("--global").arg(key).arg(value).run(builder);
|
||||||
.arg("config")
|
|
||||||
.arg("--global")
|
|
||||||
.arg(key)
|
|
||||||
.arg(value)
|
|
||||||
.as_command_mut()
|
|
||||||
.status();
|
|
||||||
let success = match status {
|
|
||||||
Ok(s) => s.success(),
|
|
||||||
Err(_) => false,
|
|
||||||
};
|
|
||||||
if !success {
|
|
||||||
panic!("git config key={key} value={value} failed (status: {status:?})");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If changing anything here, then please check that `src/ci/publish_toolstate.sh` is up to date
|
// If changing anything here, then please check that `src/ci/publish_toolstate.sh` is up to date
|
||||||
// as well.
|
// as well.
|
||||||
git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com");
|
git_config(builder, "user.email", "7378925+rust-toolstate-update@users.noreply.github.com");
|
||||||
git_config("user.name", "Rust Toolstate Update");
|
git_config(builder, "user.name", "Rust Toolstate Update");
|
||||||
git_config("credential.helper", "store");
|
git_config(builder, "credential.helper", "store");
|
||||||
|
|
||||||
let credential = format!("https://{token}:x-oauth-basic@github.com\n",);
|
let credential = format!("https://{token}:x-oauth-basic@github.com\n",);
|
||||||
let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials");
|
let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials");
|
||||||
@ -403,55 +374,51 @@ fn read_old_toolstate() -> Vec<RepoState> {
|
|||||||
///
|
///
|
||||||
/// * See <https://help.github.com/articles/about-commit-email-addresses/>
|
/// * See <https://help.github.com/articles/about-commit-email-addresses/>
|
||||||
/// if a private email by GitHub is wanted.
|
/// if a private email by GitHub is wanted.
|
||||||
fn commit_toolstate_change(current_toolstate: &ToolstateData) {
|
fn commit_toolstate_change(builder: &Builder<'_>, current_toolstate: &ToolstateData) {
|
||||||
let message = format!("({} CI update)", OS.expect("linux/windows only"));
|
let message = format!("({} CI update)", OS.expect("linux/windows only"));
|
||||||
let mut success = false;
|
let mut success = false;
|
||||||
for _ in 1..=5 {
|
for _ in 1..=5 {
|
||||||
// Upload the test results (the new commit-to-toolstate mapping) to the toolstate repo.
|
// Upload the test results (the new commit-to-toolstate mapping) to the toolstate repo.
|
||||||
// This does *not* change the "current toolstate"; that only happens post-landing
|
// This does *not* change the "current toolstate"; that only happens post-landing
|
||||||
// via `src/ci/docker/publish_toolstate.sh`.
|
// via `src/ci/docker/publish_toolstate.sh`.
|
||||||
publish_test_results(current_toolstate);
|
publish_test_results(builder, current_toolstate);
|
||||||
|
|
||||||
// `git commit` failing means nothing to commit.
|
// `git commit` failing means nothing to commit.
|
||||||
let status = t!(helpers::git(Some(Path::new(TOOLSTATE_DIR)))
|
let status = helpers::git(Some(Path::new(TOOLSTATE_DIR)))
|
||||||
|
.allow_failure()
|
||||||
.arg("commit")
|
.arg("commit")
|
||||||
.arg("-a")
|
.arg("-a")
|
||||||
.arg("-m")
|
.arg("-m")
|
||||||
.arg(&message)
|
.arg(&message)
|
||||||
.as_command_mut()
|
.run(builder);
|
||||||
.status());
|
if !status.is_success() {
|
||||||
if !status.success() {
|
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let status = t!(helpers::git(Some(Path::new(TOOLSTATE_DIR)))
|
let status = helpers::git(Some(Path::new(TOOLSTATE_DIR)))
|
||||||
|
.allow_failure()
|
||||||
.arg("push")
|
.arg("push")
|
||||||
.arg("origin")
|
.arg("origin")
|
||||||
.arg("master")
|
.arg("master")
|
||||||
.as_command_mut()
|
.run(builder);
|
||||||
.status());
|
|
||||||
// If we successfully push, exit.
|
// If we successfully push, exit.
|
||||||
if status.success() {
|
if status.is_success() {
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
eprintln!("Sleeping for 3 seconds before retrying push");
|
eprintln!("Sleeping for 3 seconds before retrying push");
|
||||||
std::thread::sleep(std::time::Duration::from_secs(3));
|
std::thread::sleep(std::time::Duration::from_secs(3));
|
||||||
let status = t!(helpers::git(Some(Path::new(TOOLSTATE_DIR)))
|
helpers::git(Some(Path::new(TOOLSTATE_DIR)))
|
||||||
.arg("fetch")
|
.arg("fetch")
|
||||||
.arg("origin")
|
.arg("origin")
|
||||||
.arg("master")
|
.arg("master")
|
||||||
.as_command_mut()
|
.run(builder);
|
||||||
.status());
|
helpers::git(Some(Path::new(TOOLSTATE_DIR)))
|
||||||
assert!(status.success());
|
|
||||||
let status = t!(helpers::git(Some(Path::new(TOOLSTATE_DIR)))
|
|
||||||
.arg("reset")
|
.arg("reset")
|
||||||
.arg("--hard")
|
.arg("--hard")
|
||||||
.arg("origin/master")
|
.arg("origin/master")
|
||||||
.as_command_mut()
|
.run(builder);
|
||||||
.status());
|
|
||||||
assert!(status.success());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !success {
|
if !success {
|
||||||
@ -464,9 +431,8 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData) {
|
|||||||
/// These results will later be promoted to `latest.json` by the
|
/// These results will later be promoted to `latest.json` by the
|
||||||
/// `publish_toolstate.py` script if the PR passes all tests and is merged to
|
/// `publish_toolstate.py` script if the PR passes all tests and is merged to
|
||||||
/// master.
|
/// master.
|
||||||
fn publish_test_results(current_toolstate: &ToolstateData) {
|
fn publish_test_results(builder: &Builder<'_>, current_toolstate: &ToolstateData) {
|
||||||
let commit = t!(helpers::git(None).arg("rev-parse").arg("HEAD").as_command_mut().output());
|
let commit = helpers::git(None).capture().arg("rev-parse").arg("HEAD").run(builder).stdout();
|
||||||
let commit = t!(String::from_utf8(commit.stdout));
|
|
||||||
|
|
||||||
let toolstate_serialized = t!(serde_json::to_string(¤t_toolstate));
|
let toolstate_serialized = t!(serde_json::to_string(¤t_toolstate));
|
||||||
|
|
||||||
|
@ -2108,7 +2108,7 @@ impl<'a> Builder<'a> {
|
|||||||
// Try to use a sysroot-relative bindir, in case it was configured absolutely.
|
// Try to use a sysroot-relative bindir, in case it was configured absolutely.
|
||||||
cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative());
|
cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative());
|
||||||
|
|
||||||
self.ci_env.force_coloring_in_ci(cargo.as_command_mut());
|
cargo.force_coloring_in_ci(self.ci_env);
|
||||||
|
|
||||||
// When we build Rust dylibs they're all intended for intermediate
|
// When we build Rust dylibs they're all intended for intermediate
|
||||||
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
|
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
|
||||||
|
@ -23,7 +23,7 @@ use std::fmt::Display;
|
|||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::Command;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
@ -36,7 +36,7 @@ use utils::channel::GitInfo;
|
|||||||
use utils::helpers::hex_encode;
|
use utils::helpers::hex_encode;
|
||||||
|
|
||||||
use crate::core::builder;
|
use crate::core::builder;
|
||||||
use crate::core::builder::Kind;
|
use crate::core::builder::{Builder, Kind};
|
||||||
use crate::core::config::{flags, LldMode};
|
use crate::core::config::{flags, LldMode};
|
||||||
use crate::core::config::{DryRun, Target};
|
use crate::core::config::{DryRun, Target};
|
||||||
use crate::core::config::{LlvmLibunwind, TargetSelection};
|
use crate::core::config::{LlvmLibunwind, TargetSelection};
|
||||||
@ -489,18 +489,29 @@ impl Build {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let submodule_git = || helpers::git(Some(&absolute_path));
|
// Submodule updating actually happens during in the dry run mode. We need to make sure that
|
||||||
|
// all the git commands below are actually executed, because some follow-up code
|
||||||
|
// in bootstrap might depend on the submodules being checked out. Furthermore, not all
|
||||||
|
// the command executions below work with an empty output (produced during dry run).
|
||||||
|
// Therefore, all commands below are marked with `run_always()`, so that they also run in
|
||||||
|
// dry run mode.
|
||||||
|
let submodule_git = || {
|
||||||
|
let mut cmd = helpers::git(Some(&absolute_path)).capture_stdout();
|
||||||
|
cmd.run_always();
|
||||||
|
cmd
|
||||||
|
};
|
||||||
|
|
||||||
// Determine commit checked out in submodule.
|
// Determine commit checked out in submodule.
|
||||||
let checked_out_hash = output(submodule_git().args(["rev-parse", "HEAD"]).as_command_mut());
|
let checked_out_hash = submodule_git().args(["rev-parse", "HEAD"]).run(self).stdout();
|
||||||
let checked_out_hash = checked_out_hash.trim_end();
|
let checked_out_hash = checked_out_hash.trim_end();
|
||||||
// Determine commit that the submodule *should* have.
|
// Determine commit that the submodule *should* have.
|
||||||
let recorded = output(
|
let recorded = helpers::git(Some(&self.src))
|
||||||
helpers::git(Some(&self.src))
|
.capture_stdout()
|
||||||
.args(["ls-tree", "HEAD"])
|
.run_always()
|
||||||
.arg(relative_path)
|
.args(["ls-tree", "HEAD"])
|
||||||
.as_command_mut(),
|
.arg(relative_path)
|
||||||
);
|
.run(self)
|
||||||
|
.stdout();
|
||||||
let actual_hash = recorded
|
let actual_hash = recorded
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
.nth(2)
|
.nth(2)
|
||||||
@ -513,6 +524,7 @@ impl Build {
|
|||||||
|
|
||||||
println!("Updating submodule {}", relative_path.display());
|
println!("Updating submodule {}", relative_path.display());
|
||||||
helpers::git(Some(&self.src))
|
helpers::git(Some(&self.src))
|
||||||
|
.run_always()
|
||||||
.args(["submodule", "-q", "sync"])
|
.args(["submodule", "-q", "sync"])
|
||||||
.arg(relative_path)
|
.arg(relative_path)
|
||||||
.run(self);
|
.run(self);
|
||||||
@ -521,21 +533,16 @@ impl Build {
|
|||||||
let update = |progress: bool| {
|
let update = |progress: bool| {
|
||||||
// Git is buggy and will try to fetch submodules from the tracking branch for *this* repository,
|
// Git is buggy and will try to fetch submodules from the tracking branch for *this* repository,
|
||||||
// even though that has no relation to the upstream for the submodule.
|
// even though that has no relation to the upstream for the submodule.
|
||||||
let current_branch = {
|
let current_branch = helpers::git(Some(&self.src))
|
||||||
let output = helpers::git(Some(&self.src))
|
.capture_stdout()
|
||||||
.args(["symbolic-ref", "--short", "HEAD"])
|
.run_always()
|
||||||
.as_command_mut()
|
.args(["symbolic-ref", "--short", "HEAD"])
|
||||||
.stderr(Stdio::inherit())
|
.run(self)
|
||||||
.output();
|
.stdout_if_ok()
|
||||||
let output = t!(output);
|
.map(|s| s.trim().to_owned());
|
||||||
if output.status.success() {
|
|
||||||
Some(String::from_utf8(output.stdout).unwrap().trim().to_owned())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut git = helpers::git(Some(&self.src));
|
let mut git = helpers::git(Some(&self.src)).allow_failure();
|
||||||
|
git.run_always();
|
||||||
if let Some(branch) = current_branch {
|
if let Some(branch) = current_branch {
|
||||||
// If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name.
|
// If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name.
|
||||||
// This syntax isn't accepted by `branch.{branch}`. Strip it.
|
// This syntax isn't accepted by `branch.{branch}`. Strip it.
|
||||||
@ -549,8 +556,7 @@ impl Build {
|
|||||||
git.arg(relative_path);
|
git.arg(relative_path);
|
||||||
git
|
git
|
||||||
};
|
};
|
||||||
// NOTE: doesn't use `try_run` because this shouldn't print an error if it fails.
|
if !update(true).run(self).is_success() {
|
||||||
if !update(true).as_command_mut().status().map_or(false, |status| status.success()) {
|
|
||||||
update(false).run(self);
|
update(false).run(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1946,22 +1952,28 @@ fn envify(s: &str) -> String {
|
|||||||
///
|
///
|
||||||
/// In case of errors during `git` command execution (e.g., in tarball sources), default values
|
/// In case of errors during `git` command execution (e.g., in tarball sources), default values
|
||||||
/// are used to prevent panics.
|
/// are used to prevent panics.
|
||||||
pub fn generate_smart_stamp_hash(dir: &Path, additional_input: &str) -> String {
|
pub fn generate_smart_stamp_hash(
|
||||||
|
builder: &Builder<'_>,
|
||||||
|
dir: &Path,
|
||||||
|
additional_input: &str,
|
||||||
|
) -> String {
|
||||||
let diff = helpers::git(Some(dir))
|
let diff = helpers::git(Some(dir))
|
||||||
|
.capture_stdout()
|
||||||
|
.allow_failure()
|
||||||
.arg("diff")
|
.arg("diff")
|
||||||
.as_command_mut()
|
.run(builder)
|
||||||
.output()
|
.stdout_if_ok()
|
||||||
.map(|o| String::from_utf8(o.stdout).unwrap_or_default())
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let status = helpers::git(Some(dir))
|
let status = helpers::git(Some(dir))
|
||||||
|
.capture_stdout()
|
||||||
|
.allow_failure()
|
||||||
.arg("status")
|
.arg("status")
|
||||||
.arg("--porcelain")
|
.arg("--porcelain")
|
||||||
.arg("-z")
|
.arg("-z")
|
||||||
.arg("--untracked-files=normal")
|
.arg("--untracked-files=normal")
|
||||||
.as_command_mut()
|
.run(builder)
|
||||||
.output()
|
.stdout_if_ok()
|
||||||
.map(|o| String::from_utf8(o.stdout).unwrap_or_default())
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut hasher = sha2::Sha256::new();
|
let mut hasher = sha2::Sha256::new();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::Build;
|
use crate::Build;
|
||||||
|
use build_helper::ci::CiEnv;
|
||||||
use build_helper::drop_bomb::DropBomb;
|
use build_helper::drop_bomb::DropBomb;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
@ -171,6 +172,18 @@ impl BootstrapCommand {
|
|||||||
pub fn get_created_location(&self) -> std::panic::Location<'static> {
|
pub fn get_created_location(&self) -> std::panic::Location<'static> {
|
||||||
self.drop_bomb.get_created_location()
|
self.drop_bomb.get_created_location()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If in a CI environment, forces the command to run with colors.
|
||||||
|
pub fn force_coloring_in_ci(&mut self, ci_env: CiEnv) {
|
||||||
|
if ci_env != CiEnv::None {
|
||||||
|
// Due to use of stamp/docker, the output stream of bootstrap is not
|
||||||
|
// a TTY in CI, so coloring is by-default turned off.
|
||||||
|
// The explicit `TERM=xterm` environment is needed for
|
||||||
|
// `--color always` to actually work. This env var was lost when
|
||||||
|
// compiling through the Makefile. Very strange.
|
||||||
|
self.env("TERM", "xterm").args(["--color", "always"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for BootstrapCommand {
|
impl Debug for BootstrapCommand {
|
||||||
|
@ -338,13 +338,13 @@ fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
|
|||||||
/// When `clang-cl` is used with instrumentation, we need to add clang's runtime library resource
|
/// When `clang-cl` is used with instrumentation, we need to add clang's runtime library resource
|
||||||
/// directory to the linker flags, otherwise there will be linker errors about the profiler runtime
|
/// directory to the linker flags, otherwise there will be linker errors about the profiler runtime
|
||||||
/// missing. This function returns the path to that directory.
|
/// missing. This function returns the path to that directory.
|
||||||
pub fn get_clang_cl_resource_dir(clang_cl_path: &str) -> PathBuf {
|
pub fn get_clang_cl_resource_dir(builder: &Builder<'_>, clang_cl_path: &str) -> PathBuf {
|
||||||
// Similar to how LLVM does it, to find clang's library runtime directory:
|
// Similar to how LLVM does it, to find clang's library runtime directory:
|
||||||
// - we ask `clang-cl` to locate the `clang_rt.builtins` lib.
|
// - we ask `clang-cl` to locate the `clang_rt.builtins` lib.
|
||||||
let mut builtins_locator = Command::new(clang_cl_path);
|
let mut builtins_locator = command(clang_cl_path);
|
||||||
builtins_locator.args(["/clang:-print-libgcc-file-name", "/clang:--rtlib=compiler-rt"]);
|
builtins_locator.args(["/clang:-print-libgcc-file-name", "/clang:--rtlib=compiler-rt"]);
|
||||||
|
|
||||||
let clang_rt_builtins = output(&mut builtins_locator);
|
let clang_rt_builtins = builtins_locator.capture_stdout().run(builder).stdout();
|
||||||
let clang_rt_builtins = Path::new(clang_rt_builtins.trim());
|
let clang_rt_builtins = Path::new(clang_rt_builtins.trim());
|
||||||
assert!(
|
assert!(
|
||||||
clang_rt_builtins.exists(),
|
clang_rt_builtins.exists(),
|
||||||
|
@ -369,13 +369,13 @@ impl<'a> Tarball<'a> {
|
|||||||
// gets the same timestamp.
|
// gets the same timestamp.
|
||||||
if self.builder.rust_info().is_managed_git_subrepository() {
|
if self.builder.rust_info().is_managed_git_subrepository() {
|
||||||
// %ct means committer date
|
// %ct means committer date
|
||||||
let timestamp = helpers::output(
|
let timestamp = helpers::git(Some(&self.builder.src))
|
||||||
helpers::git(Some(&self.builder.src))
|
.capture_stdout()
|
||||||
.arg("log")
|
.arg("log")
|
||||||
.arg("-1")
|
.arg("-1")
|
||||||
.arg("--format=%ct")
|
.arg("--format=%ct")
|
||||||
.as_command_mut(),
|
.run(self.builder)
|
||||||
);
|
.stdout();
|
||||||
cmd.args(["--override-file-mtime", timestamp.trim()]);
|
cmd.args(["--override-file-mtime", timestamp.trim()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use std::process::Command;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum CiEnv {
|
pub enum CiEnv {
|
||||||
/// Not a CI environment.
|
/// Not a CI environment.
|
||||||
@ -21,18 +19,6 @@ impl CiEnv {
|
|||||||
pub fn is_ci() -> bool {
|
pub fn is_ci() -> bool {
|
||||||
Self::current() != CiEnv::None
|
Self::current() != CiEnv::None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If in a CI environment, forces the command to run with colors.
|
|
||||||
pub fn force_coloring_in_ci(self, cmd: &mut Command) {
|
|
||||||
if self != CiEnv::None {
|
|
||||||
// Due to use of stamp/docker, the output stream of bootstrap is not
|
|
||||||
// a TTY in CI, so coloring is by-default turned off.
|
|
||||||
// The explicit `TERM=xterm` environment is needed for
|
|
||||||
// `--color always` to actually work. This env var was lost when
|
|
||||||
// compiling through the Makefile. Very strange.
|
|
||||||
cmd.env("TERM", "xterm").args(&["--color", "always"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod gha {
|
pub mod gha {
|
||||||
|
Loading…
Reference in New Issue
Block a user