move bootstrap core implementation to bootstrap/src/core module

Signed-off-by: onur-ozkan <work@onurozkan.dev>
This commit is contained in:
onur-ozkan 2023-10-07 23:37:06 +03:00
parent c68ab9347e
commit 2bce0207d4
24 changed files with 792 additions and 189 deletions

View File

@ -1,10 +1,12 @@
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
use crate::builder::{crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
use crate::config::TargetSelection;
use crate::tool::{prepare_tool_cargo, SourceType};
use crate::core::build_steps::compile::{
add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
};
use crate::core::build_steps::tool::{prepare_tool_cargo, SourceType};
use crate::core::builder::{crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::TargetSelection;
use crate::utils::cache::Interned;
use crate::INTERNER;
use crate::{Compiler, Mode, Subcommand};
use std::path::{Path, PathBuf};
@ -16,7 +18,7 @@ pub struct Std {
///
/// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
///
/// [`compile::Rustc`]: crate::compile::Rustc
/// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc
crates: Interned<Vec<String>>,
}
@ -193,7 +195,7 @@ pub struct Rustc {
///
/// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
///
/// [`compile::Rustc`]: crate::compile::Rustc
/// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc
crates: Interned<Vec<String>>,
}
@ -237,8 +239,8 @@ impl Step for Rustc {
// the sysroot for the compiler to find. Otherwise, we're going to
// fail when building crates that need to generate code (e.g., build
// scripts and their dependencies).
builder.ensure(crate::compile::Std::new(compiler, compiler.host));
builder.ensure(crate::compile::Std::new(compiler, target));
builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
} else {
builder.ensure(Std::new(target));
}
@ -387,7 +389,7 @@ impl Step for RustAnalyzer {
&["rust-analyzer/in-rust-tree".to_owned()],
);
cargo.allow_features(crate::tool::RustAnalyzer::ALLOW_FEATURES);
cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
// For ./x.py clippy, don't check those targets because
// linting tests and benchmarks can produce very noisy results

View File

@ -9,9 +9,9 @@ use std::fs;
use std::io::{self, ErrorKind};
use std::path::Path;
use crate::builder::{crate_description, Builder, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
use crate::util::t;
use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step};
use crate::utils::cache::Interned;
use crate::utils::helpers::t;
use crate::{Build, Compiler, Mode, Subcommand};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

View File

@ -19,16 +19,17 @@ use std::str;
use serde_derive::Deserialize;
use crate::builder::crate_description;
use crate::builder::Cargo;
use crate::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath};
use crate::cache::{Interned, INTERNER};
use crate::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
use crate::dist;
use crate::llvm;
use crate::tool::SourceType;
use crate::util::get_clang_cl_resource_dir;
use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date};
use crate::core::build_steps::dist;
use crate::core::build_steps::llvm;
use crate::core::build_steps::tool::SourceType;
use crate::core::builder::crate_description;
use crate::core::builder::Cargo;
use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath};
use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
use crate::utils::cache::{Interned, INTERNER};
use crate::utils::helpers::{
exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date,
};
use crate::LLVM_TOOLS;
use crate::{CLang, Compiler, DependencyType, GitRepo, Mode};
use filetime::FileTime;
@ -510,7 +511,7 @@ impl Step for StdLink {
let (libdir, hostdir) = if self.force_recompile && builder.download_rustc() {
// NOTE: copies part of `sysroot_libdir` to avoid having to add a new `force_recompile` argument there too
let lib = builder.sysroot_libdir_relative(self.compiler);
let sysroot = builder.ensure(crate::compile::Sysroot {
let sysroot = builder.ensure(crate::core::build_steps::compile::Sysroot {
compiler: self.compiler,
force_recompile: self.force_recompile,
});
@ -1016,7 +1017,8 @@ pub fn rustc_cargo_env(
// detected that LLVM is already built and good to go which helps prevent
// busting caches (e.g. like #71152).
if builder.config.llvm_enabled() {
let building_is_expensive = crate::llvm::prebuilt_llvm_config(builder, target).is_err();
let building_is_expensive =
crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target).is_err();
// `top_stage == stage` might be false for `check --stage 1`, if we are building the stage 1 compiler
let can_skip_build = builder.kind == Kind::Check && builder.top_stage == stage;
let should_skip_build = building_is_expensive && can_skip_build;
@ -1684,7 +1686,7 @@ impl Step for Assemble {
builder.copy(&lld_install.join("bin").join(&src_exe), &libdir_bin.join(&dst_exe));
let self_contained_lld_dir = libdir_bin.join("gcc-ld");
t!(fs::create_dir(&self_contained_lld_dir));
let lld_wrapper_exe = builder.ensure(crate::tool::LldWrapper {
let lld_wrapper_exe = builder.ensure(crate::core::build_steps::tool::LldWrapper {
compiler: build_compiler,
target: target_compiler.host,
});

View File

@ -19,16 +19,16 @@ use std::process::Command;
use object::read::archive::ArchiveFile;
use object::BinaryFormat;
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
use crate::channel;
use crate::compile;
use crate::config::TargetSelection;
use crate::doc::DocumentationFormat;
use crate::llvm;
use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
use crate::tool::{self, Tool};
use crate::util::{exe, is_dylib, output, t, timeit};
use crate::core::build_steps::compile;
use crate::core::build_steps::doc::DocumentationFormat;
use crate::core::build_steps::llvm;
use crate::core::build_steps::tool::{self, Tool};
use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::TargetSelection;
use crate::utils::cache::{Interned, INTERNER};
use crate::utils::channel;
use crate::utils::helpers::{exe, is_dylib, output, t, timeit};
use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
@ -104,7 +104,7 @@ impl Step for JsonDocs {
/// Builds the `rust-docs-json` installer component.
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let host = self.host;
builder.ensure(crate::doc::Std::new(
builder.ensure(crate::core::build_steps::doc::Std::new(
builder.top_stage,
host,
builder,
@ -488,7 +488,7 @@ impl Step for Rustc {
let man_src = builder.src.join("src/doc/man");
let man_dst = image.join("share/man/man1");
// don't use our `bootstrap::util::{copy, cp_r}`, because those try
// don't use our `bootstrap::{copy, cp_r}`, because those try
// to hardlink, and we don't want to edit the source templates
for file_entry in builder.read_dir(&man_src) {
let page_src = file_entry.path();
@ -2060,7 +2060,7 @@ impl Step for LlvmTools {
}
}
builder.ensure(crate::llvm::Llvm { target });
builder.ensure(crate::core::build_steps::llvm::Llvm { target });
let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
tarball.set_overlay(OverlayKind::LLVM);
@ -2119,10 +2119,10 @@ impl Step for RustDev {
let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
tarball.set_overlay(OverlayKind::LLVM);
builder.ensure(crate::llvm::Llvm { target });
builder.ensure(crate::core::build_steps::llvm::Llvm { target });
// We want to package `lld` to use it with `download-ci-llvm`.
builder.ensure(crate::llvm::Lld { target });
builder.ensure(crate::core::build_steps::llvm::Lld { target });
let src_bindir = builder.llvm_out(target).join("bin");
// If updating this list, you likely want to change

View File

@ -10,13 +10,13 @@
use std::fs;
use std::path::{Path, PathBuf};
use crate::builder::crate_description;
use crate::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
use crate::compile;
use crate::config::{Config, TargetSelection};
use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
use crate::util::{dir_is_empty, symlink_dir, t, up_to_date};
use crate::core::build_steps::compile;
use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool};
use crate::core::builder::crate_description;
use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::{Config, TargetSelection};
use crate::utils::cache::{Interned, INTERNER};
use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date};
use crate::Mode;
macro_rules! submodule_helper {

View File

@ -1,7 +1,7 @@
//! Runs rustfmt on the repository.
use crate::builder::Builder;
use crate::util::{output, program_out_of_date, t};
use crate::core::builder::Builder;
use crate::utils::helpers::{output, program_out_of_date, t};
use build_helper::ci::CiEnv;
use build_helper::git::get_git_modified_files;
use ignore::WalkBuilder;

View File

@ -8,15 +8,13 @@ use std::fs;
use std::path::{Component, Path, PathBuf};
use std::process::Command;
use crate::util::t;
use crate::dist;
use crate::tarball::GeneratedTarball;
use crate::core::build_steps::dist;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::core::config::{Config, TargetSelection};
use crate::utils::helpers::t;
use crate::utils::tarball::GeneratedTarball;
use crate::{Compiler, Kind};
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::config::{Config, TargetSelection};
#[cfg(target_os = "illumos")]
const SHELL: &str = "bash";
#[cfg(not(target_os = "illumos"))]

View File

@ -16,11 +16,10 @@ use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::channel;
use crate::config::{Config, TargetSelection};
use crate::util::get_clang_cl_resource_dir;
use crate::util::{self, exe, output, t, up_to_date};
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::core::config::{Config, TargetSelection};
use crate::utils::channel;
use crate::utils::helpers::{self, exe, get_clang_cl_resource_dir, output, t, up_to_date};
use crate::{CLang, GitRepo, Kind};
use build_helper::ci::CiEnv;
@ -281,7 +280,7 @@ impl Step for Llvm {
let _guard = builder.msg_unstaged(Kind::Build, "LLVM", target);
t!(stamp.remove());
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
t!(fs::create_dir_all(&out_dir));
// https://llvm.org/docs/CMake.html
@ -410,7 +409,7 @@ impl Step for Llvm {
let mut enabled_llvm_projects = Vec::new();
if util::forcing_clang_based_tests() {
if helpers::forcing_clang_based_tests() {
enabled_llvm_projects.push("clang");
enabled_llvm_projects.push("compiler-rt");
}
@ -528,8 +527,12 @@ impl Step for Llvm {
// If the shared library exists in LLVM's `/build/lib/` or `/lib/` folders, strip its
// debuginfo.
crate::compile::strip_debug(builder, target, &out_dir.join("lib").join(&lib_name));
crate::compile::strip_debug(
crate::core::build_steps::compile::strip_debug(
builder,
target,
&out_dir.join("lib").join(&lib_name),
);
crate::core::build_steps::compile::strip_debug(
builder,
target,
&out_dir.join("build").join("lib").join(&lib_name),
@ -846,7 +849,7 @@ impl Step for Lld {
}
let _guard = builder.msg_unstaged(Kind::Build, "LLD", target);
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
t!(fs::create_dir_all(&out_dir));
let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/lld"));
@ -877,7 +880,7 @@ impl Step for Lld {
// `LD_LIBRARY_PATH` overrides)
//
if builder.config.rpath_enabled(target)
&& util::use_host_linker(target)
&& helpers::use_host_linker(target)
&& builder.config.llvm_link_shared()
&& target.contains("linux")
{
@ -970,7 +973,7 @@ impl Step for Sanitizers {
let _guard = builder.msg_unstaged(Kind::Build, "sanitizers", self.target);
t!(stamp.remove());
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
let mut cfg = cmake::Config::new(&compiler_rt_dir);
cfg.profile("Release");

View File

@ -0,0 +1,15 @@
pub(crate) mod check;
pub(crate) mod clean;
pub(crate) mod compile;
pub(crate) mod dist;
pub(crate) mod doc;
pub(crate) mod format;
pub(crate) mod install;
pub(crate) mod llvm;
pub(crate) mod run;
pub(crate) mod setup;
pub(crate) mod suggest;
pub(crate) mod synthetic_targets;
pub(crate) mod test;
pub(crate) mod tool;
pub(crate) mod toolstate;

View File

@ -1,13 +1,15 @@
use std::path::PathBuf;
use std::process::Command;
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::config::TargetSelection;
use crate::dist::distdir;
use crate::flags::get_completion;
use crate::test;
use crate::tool::{self, SourceType, Tool};
use crate::util::output;
use clap_complete::shells;
use crate::core::build_steps::dist::distdir;
use crate::core::build_steps::test;
use crate::core::build_steps::tool::{self, SourceType, Tool};
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::core::config::flags::get_completion;
use crate::core::config::TargetSelection;
use crate::utils::helpers::output;
use crate::Mode;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]

View File

@ -1,4 +1,4 @@
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::Config;
use crate::{t, CONFIG_CHANGE_HISTORY};
use sha2::Digest;
@ -12,6 +12,7 @@ use std::str::FromStr;
use std::{fmt, fs, io};
#[cfg(test)]
#[path = "../../tests/setup.rs"]
mod tests;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
@ -35,7 +36,7 @@ static SETTINGS_HASHES: &[&str] = &[
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
];
static RUST_ANALYZER_SETTINGS: &str = include_str!("../etc/rust_analyzer_settings.json");
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json");
impl Profile {
fn include_path(&self, src_path: &Path) -> PathBuf {

View File

@ -1,12 +1,11 @@
#![cfg_attr(feature = "build-metrics", allow(unused))]
use clap::Parser;
use std::path::PathBuf;
use std::str::FromStr;
use std::path::PathBuf;
use clap::Parser;
use crate::{builder::Builder, tool::Tool};
use crate::core::build_steps::tool::Tool;
use crate::core::builder::Builder;
/// Suggests a list of possible `x.py` commands to run based on modified files in branch.
pub fn suggest(builder: &Builder<'_>, run: bool) {
@ -62,7 +61,7 @@ pub fn suggest(builder: &Builder<'_>, run: bool) {
for sug in suggestions {
let mut build: crate::Build = builder.build.clone();
build.config.paths = sug.2;
build.config.cmd = crate::flags::Flags::parse_from(["x.py", sug.0]).cmd;
build.config.cmd = crate::core::config::flags::Flags::parse_from(["x.py", sug.0]).cmd;
if let Some(stage) = sug.1 {
build.config.stage = stage;
}

View File

@ -7,8 +7,8 @@
//! one of the target specs already defined in this module, or create new ones by adding a new step
//! that calls create_synthetic_target.
use crate::builder::{Builder, ShouldRun, Step};
use crate::config::TargetSelection;
use crate::core::builder::{Builder, ShouldRun, Step};
use crate::core::config::TargetSelection;
use crate::Compiler;
use std::process::{Command, Stdio};
@ -76,7 +76,7 @@ fn create_synthetic_target(
std::fs::write(&path, &serde_json::to_vec_pretty(&spec).unwrap()).unwrap();
let target = TargetSelection::create_synthetic(&name, path.to_str().unwrap());
crate::cc_detect::find_target(builder, target);
crate::utils::cc_detect::find_target(builder, target);
target
}

View File

@ -13,21 +13,24 @@ use std::process::{Command, Stdio};
use clap_complete::shells;
use crate::builder::crate_description;
use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
use crate::cache::INTERNER;
use crate::compile;
use crate::config::TargetSelection;
use crate::dist;
use crate::doc::DocumentationFormat;
use crate::flags::Subcommand;
use crate::llvm;
use crate::render_tests::add_flags_and_try_run_tests;
use crate::synthetic_targets::MirOptPanicAbortSyntheticTarget;
use crate::tool::{self, SourceType, Tool};
use crate::toolstate::ToolState;
use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t, up_to_date};
use crate::core::build_steps::compile;
use crate::core::build_steps::dist;
use crate::core::build_steps::doc::DocumentationFormat;
use crate::core::build_steps::llvm;
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
use crate::core::build_steps::tool::{self, SourceType, Tool};
use crate::core::build_steps::toolstate::ToolState;
use crate::core::builder::crate_description;
use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::flags::get_completion;
use crate::core::config::flags::Subcommand;
use crate::core::config::TargetSelection;
use crate::utils;
use crate::utils::cache::{Interned, INTERNER};
use crate::utils::helpers::{
self, add_link_lib_path, dylib_path, dylib_path_var, output, t, up_to_date,
};
use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
use crate::{envify, CLang, DocTests, GitRepo, Mode};
const ADB_TEST_DIR: &str = "/data/local/tmp/work";
@ -167,7 +170,7 @@ You can skip linkcheck with --skip src/tools/linkchecker"
// Run the linkchecker.
let _guard =
builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host);
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
builder.run_delaying_failure(linkchecker.arg(builder.out.join(host.triple).join("doc")));
}
@ -219,7 +222,11 @@ impl Step for HtmlCheck {
}
// Ensure that a few different kinds of documentation are available.
builder.default_doc(&[]);
builder.ensure(crate::doc::Rustc::new(builder.top_stage, self.target, builder));
builder.ensure(crate::core::build_steps::doc::Rustc::new(
builder.top_stage,
self.target,
builder,
));
builder.run_delaying_failure(
builder.tool_cmd(Tool::HtmlChecker).arg(builder.doc_out(self.target)),
@ -260,7 +267,7 @@ impl Step for Cargotest {
let out_dir = builder.out.join("ct");
t!(fs::create_dir_all(&out_dir));
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
let mut cmd = builder.tool_cmd(Tool::CargoTest);
builder.run_delaying_failure(
cmd.arg(&cargo)
@ -328,7 +335,7 @@ impl Step for Cargo {
builder,
);
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
add_flags_and_try_run_tests(builder, &mut cargo);
}
}
@ -642,7 +649,7 @@ impl Step for Miri {
// does not understand the flags added by `add_flags_and_try_run_test`.
let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
{
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
builder.run(&mut cargo);
}
@ -658,7 +665,7 @@ impl Step for Miri {
let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
{
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
builder.run(&mut cargo);
}
}
@ -698,7 +705,7 @@ impl Step for Miri {
let mut cargo = Command::from(cargo);
{
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
builder.run(&mut cargo);
}
}
@ -859,7 +866,7 @@ impl Step for RustdocTheme {
if builder.is_fuse_ld_lld(self.compiler.host) {
cmd.env(
"RUSTDOC_LLD_NO_THREADS",
util::lld_flag_no_threads(self.compiler.host.contains("windows")),
helpers::lld_flag_no_threads(self.compiler.host.contains("windows")),
);
}
builder.run_delaying_failure(&mut cmd);
@ -900,7 +907,8 @@ impl Step for RustdocJSStd {
.arg("--test-folder")
.arg(builder.src.join("tests/rustdoc-js-std"));
for path in &builder.paths {
if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder) {
if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
{
if !p.ends_with(".js") {
eprintln!("A non-js file was given: `{}`", path.display());
panic!("Cannot run rustdoc-js-std tests");
@ -908,7 +916,7 @@ impl Step for RustdocJSStd {
command.arg("--test-file").arg(path);
}
}
builder.ensure(crate::doc::Std::new(
builder.ensure(crate::core::build_steps::doc::Std::new(
builder.top_stage,
self.target,
builder,
@ -1035,7 +1043,7 @@ impl Step for RustdocGUI {
.env("RUSTC", builder.rustc(self.compiler));
for path in &builder.paths {
if let Some(p) = util::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
if !p.ends_with(".goml") {
eprintln!("A non-goml file was given: `{}`", path.display());
panic!("Cannot run rustdoc-gui tests");
@ -1058,7 +1066,7 @@ impl Step for RustdocGUI {
cmd.arg("--npm").arg(npm);
}
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
let _guard = builder.msg_sysroot_tool(
Kind::Test,
self.compiler.stage,
@ -1066,7 +1074,7 @@ impl Step for RustdocGUI {
self.compiler.host,
self.target,
);
crate::render_tests::try_run_tests(builder, &mut cmd, true);
try_run_tests(builder, &mut cmd, true);
}
}
@ -1126,7 +1134,7 @@ help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to
);
crate::exit!(1);
}
crate::format::format(&builder, !builder.config.cmd.bless(), &[]);
crate::core::build_steps::format::format(&builder, !builder.config.cmd.bless(), &[]);
}
builder.info("tidy check");
@ -1138,10 +1146,10 @@ help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to
let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"]
.map(|filename| builder.src.join("src/etc/completions").join(filename));
if builder.config.cmd.bless() {
builder.ensure(crate::run::GenerateCompletions);
} else if crate::flags::get_completion(shells::Bash, &bash).is_some()
|| crate::flags::get_completion(shells::Fish, &fish).is_some()
|| crate::flags::get_completion(shells::PowerShell, &powershell).is_some()
builder.ensure(crate::core::build_steps::run::GenerateCompletions);
} else if get_completion(shells::Bash, &bash).is_some()
|| get_completion(shells::Fish, &fish).is_some()
|| get_completion(shells::PowerShell, &powershell).is_some()
|| crate::flags::get_completion(shells::Zsh, &zsh).is_some()
{
eprintln!(
@ -1403,10 +1411,10 @@ impl Step for MirOpt {
// have been detected by bootstrap if the target we're testing wasn't in the
// --target flags.
if !builder.cc.borrow().contains_key(&target_32bit) {
crate::cc_detect::find_target(builder, target_32bit);
utils::cc_detect::find_target(builder, target_32bit);
}
if !builder.cc.borrow().contains_key(&target_64bit) {
crate::cc_detect::find_target(builder, target_64bit);
utils::cc_detect::find_target(builder, target_64bit);
}
vec![target_32bit, target_64bit]
@ -1679,7 +1687,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
}
}
if util::forcing_clang_based_tests() {
if helpers::forcing_clang_based_tests() {
let clang_exe = builder.llvm_out(target).join("bin").join("clang");
cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
}
@ -1698,7 +1706,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
// Get test-args by striping suite path
let mut test_args: Vec<&str> = paths
.iter()
.filter_map(|p| util::is_valid_test_suite_arg(p, suite_path, builder))
.filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
.collect();
test_args.append(&mut builder.config.test_args());
@ -1887,7 +1895,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
compiler.host,
target,
);
crate::render_tests::try_run_tests(builder, &mut cmd, false);
try_run_tests(builder, &mut cmd, false);
if let Some(compare_mode) = compare_mode {
cmd.arg("--compare-mode").arg(compare_mode);
@ -1909,8 +1917,8 @@ note: if you're sure you want to do this, please open an issue as to why. In the
"Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
suite, mode, compare_mode, &compiler.host, target
));
let _time = util::timeit(&builder);
crate::render_tests::try_run_tests(builder, &mut cmd, false);
let _time = helpers::timeit(&builder);
try_run_tests(builder, &mut cmd, false);
}
}
}
@ -1981,7 +1989,7 @@ impl BookTest {
compiler.host,
compiler.host,
);
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
let toolstate = if builder.run_delaying_failure(&mut rustbook_cmd) {
ToolState::TestPass
} else {
@ -2003,7 +2011,7 @@ impl BookTest {
// Do a breadth-first traversal of the `src/doc` directory and just run
// tests for all files that end in `*.md`
let mut stack = vec![builder.src.join(self.path)];
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
let mut files = Vec::new();
while let Some(p) = stack.pop() {
if p.is_dir() {
@ -2114,7 +2122,7 @@ impl Step for ErrorIndex {
let guard =
builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
builder.run_quiet(&mut tool);
drop(guard);
// The tests themselves need to link to std, so make sure it is
@ -2236,7 +2244,7 @@ fn run_cargo_test<'a>(
) -> bool {
let mut cargo =
prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder);
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
let _group = description.into().and_then(|what| {
builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target)
});
@ -2631,7 +2639,7 @@ impl Step for RemoteCopyLibs {
for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) {
let f = t!(f);
let name = f.file_name().into_string().unwrap();
if util::is_dylib(&name) {
if helpers::is_dylib(&name) {
builder.run(Command::new(&tool).arg("push").arg(f.path()));
}
}
@ -2676,7 +2684,9 @@ impl Step for Distcheck {
.current_dir(&dir),
);
builder.run(
Command::new(util::make(&builder.config.build.triple)).arg("check").current_dir(&dir),
Command::new(helpers::make(&builder.config.build.triple))
.arg("check")
.current_dir(&dir),
);
// Now make sure that rust-src has all of libstd's dependencies
@ -2833,7 +2843,7 @@ impl Step for LintDocs {
/// Tests that the lint examples in the rustc book generate the correct
/// lints and have the expected format.
fn run(self, builder: &Builder<'_>) {
builder.ensure(crate::doc::RustcBook {
builder.ensure(crate::core::build_steps::doc::RustcBook {
compiler: self.compiler,
target: self.target,
validate: true,
@ -3052,7 +3062,7 @@ impl Step for CodegenCranelift {
&compiler.host,
target
));
let _time = util::timeit(&builder);
let _time = helpers::timeit(&builder);
// FIXME handle vendoring for source tarballs before removing the --skip-test below
let download_dir = builder.out.join("cg_clif_download");

View File

@ -3,12 +3,12 @@ use std::fs;
use std::path::PathBuf;
use std::process::Command;
use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
use crate::channel::GitInfo;
use crate::compile;
use crate::config::TargetSelection;
use crate::toolstate::ToolState;
use crate::util::{add_dylib_path, exe, t};
use crate::core::build_steps::compile;
use crate::core::build_steps::toolstate::ToolState;
use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
use crate::core::config::TargetSelection;
use crate::utils::channel::GitInfo;
use crate::utils::helpers::{add_dylib_path, exe, t};
use crate::Compiler;
use crate::Mode;
use crate::{gha, Kind};

View File

@ -1,5 +1,5 @@
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::util::t;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::utils::helpers::t;
use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
use std::env;

View File

@ -12,20 +12,15 @@ use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::{Duration, Instant};
use crate::cache::{Cache, Interned, INTERNER};
use crate::config::{DryRun, SplitDebuginfo, TargetSelection};
use crate::doc;
use crate::flags::{Color, Subcommand};
use crate::install;
use crate::llvm;
use crate::run;
use crate::setup;
use crate::test;
use crate::tool::{self, SourceType};
use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t};
use crate::core::build_steps::llvm;
use crate::core::build_steps::tool::{self, SourceType};
use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, setup, test};
use crate::core::config::flags::{Color, Subcommand};
use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection};
use crate::utils::cache::{Cache, Interned, INTERNER};
use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t};
use crate::Crate;
use crate::EXTRA_CHECK_CFGS;
use crate::{check, compile, Crate};
use crate::{clean, dist};
use crate::{Build, CLang, DocTests, GitRepo, Mode};
pub use crate::Compiler;
@ -36,6 +31,10 @@ pub use crate::Compiler;
use clap::ValueEnum;
use once_cell::sync::{Lazy, OnceCell};
#[cfg(test)]
#[path = "../tests/builder.rs"]
mod tests;
pub struct Builder<'a> {
pub build: &'a Build,
pub top_stage: u32,
@ -723,7 +722,7 @@ impl<'a> Builder<'a> {
check::Bootstrap
),
Kind::Test => describe!(
crate::toolstate::ToolStateCheck,
crate::core::build_steps::toolstate::ToolStateCheck,
test::ExpandYamlAnchors,
test::Tidy,
test::Ui,
@ -1297,8 +1296,8 @@ impl<'a> Builder<'a> {
// See comment in rustc_llvm/build.rs for why this is necessary, largely llvm-config
// needs to not accidentally link to libLLVM in stage0/lib.
cargo.env("REAL_LIBRARY_PATH_VAR", &util::dylib_path_var());
if let Some(e) = env::var_os(util::dylib_path_var()) {
cargo.env("REAL_LIBRARY_PATH_VAR", &helpers::dylib_path_var());
if let Some(e) = env::var_os(helpers::dylib_path_var()) {
cargo.env("REAL_LIBRARY_PATH", e);
}
@ -1311,7 +1310,7 @@ impl<'a> Builder<'a> {
// rustc_llvm. But if LLVM is stale, that'll be a tiny amount
// of work comparatively, and we'd likely need to rebuild it anyway,
// so that's okay.
if crate::llvm::prebuilt_llvm_config(self, target).is_err() {
if crate::core::build_steps::llvm::prebuilt_llvm_config(self, target).is_err() {
cargo.env("RUST_CHECK", "1");
}
}
@ -1643,7 +1642,7 @@ impl<'a> Builder<'a> {
// argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it
// fun to pass a flag to a tool to pass a flag to pass a flag to a tool
// to change a flag in a binary?
if self.config.rpath_enabled(target) && util::use_host_linker(target) {
if self.config.rpath_enabled(target) && helpers::use_host_linker(target) {
let libdir = self.sysroot_libdir_relative(compiler).to_str().unwrap();
let rpath = if target.contains("apple") {
// Note that we need to take one extra step on macOS to also pass
@ -2197,9 +2196,6 @@ impl<'a> Builder<'a> {
}
}
#[cfg(test)]
mod tests;
/// Represents flag values in `String` form with whitespace delimiter to pass it to the compiler later.
///
/// `-Z crate-attr` flags will be applied recursively on the target code using the `rustc_parse::parser::Parser`.

View File

@ -4,6 +4,7 @@
//! how the build runs.
#[cfg(test)]
#[path = "../../tests/config.rs"]
mod tests;
use std::cell::{Cell, RefCell};
@ -17,19 +18,20 @@ use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use crate::cache::{Interned, INTERNER};
use crate::cc_detect::{ndk_compiler, Language};
use crate::channel::{self, GitInfo};
use crate::compile::CODEGEN_BACKEND_PREFIX;
pub use crate::flags::Subcommand;
use crate::flags::{Color, Flags, Warnings};
use crate::util::{exe, output, t};
use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
use crate::core::config::flags::{Color, Flags, Warnings};
use crate::utils::cache::{Interned, INTERNER};
use crate::utils::cc_detect::{ndk_compiler, Language};
use crate::utils::channel::{self, GitInfo};
use crate::utils::helpers::{exe, output, t};
use build_helper::exit;
use once_cell::sync::OnceCell;
use semver::Version;
use serde::{Deserialize, Deserializer};
use serde_derive::Deserialize;
pub use crate::core::config::flags::Subcommand;
macro_rules! check_ci_llvm {
($name:expr) => {
assert!(
@ -547,7 +549,7 @@ impl Target {
/// `Config` structure.
#[derive(Deserialize, Default)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct TomlConfig {
pub(crate) struct TomlConfig {
changelog_seen: Option<usize>, // FIXME: Deprecated field. Remove it at 2024.
change_id: Option<usize>,
build: Option<Build>,
@ -1269,7 +1271,7 @@ impl Config {
// To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
if !config.out.is_absolute() {
// `canonicalize` requires the path to already exist. Use our vendored copy of `absolute` instead.
config.out = crate::util::absolute(&config.out);
config.out = crate::utils::helpers::absolute(&config.out);
}
config.initial_rustc = if let Some(rustc) = build.rustc {
@ -1527,11 +1529,12 @@ impl Config {
config.llvm_from_ci = match llvm.download_ci_llvm {
Some(StringOrBool::String(s)) => {
assert_eq!(s, "if-available", "unknown option `{s}` for download-ci-llvm");
crate::llvm::is_ci_llvm_available(&config, asserts)
crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts)
}
Some(StringOrBool::Bool(b)) => b,
None => {
config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, asserts)
config.channel == "dev"
&& crate::core::build_steps::llvm::is_ci_llvm_available(&config, asserts)
}
};
@ -1573,8 +1576,8 @@ impl Config {
config.llvm_link_shared.set(Some(true));
}
} else {
config.llvm_from_ci =
config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, false);
config.llvm_from_ci = config.channel == "dev"
&& crate::core::build_steps::llvm::is_ci_llvm_available(&config, false);
}
if let Some(t) = toml.target {

View File

@ -0,0 +1,565 @@
//! Command-line interface of the rustbuild build system.
//!
//! This module implements the command-line parsing of the build system which
//! has various flags to configure how it's run.
use std::path::{Path, PathBuf};
use clap::{CommandFactory, Parser, ValueEnum};
use crate::core::build_steps::setup::Profile;
use crate::core::builder::{Builder, Kind};
use crate::core::config::{target_selection_list, Config, TargetSelectionList};
use crate::{Build, DocTests};
#[derive(Copy, Clone, Default, Debug, ValueEnum)]
pub enum Color {
Always,
Never,
#[default]
Auto,
}
/// Whether to deny warnings, emit them as warnings, or use the default behavior
#[derive(Copy, Clone, Default, Debug, ValueEnum)]
pub enum Warnings {
Deny,
Warn,
#[default]
Default,
}
/// Deserialized version of all flags for this compile.
#[derive(Debug, Parser)]
#[clap(
override_usage = "x.py <subcommand> [options] [<paths>...]",
disable_help_subcommand(true),
about = "",
next_line_help(false)
)]
pub struct Flags {
#[command(subcommand)]
pub cmd: Subcommand,
#[arg(global(true), short, long, action = clap::ArgAction::Count)]
/// use verbose output (-vv for very verbose)
pub verbose: u8, // each extra -v after the first is passed to Cargo
#[arg(global(true), short, long)]
/// use incremental compilation
pub incremental: bool,
#[arg(global(true), long, value_hint = clap::ValueHint::FilePath, value_name = "FILE")]
/// TOML configuration file for build
pub config: Option<PathBuf>,
#[arg(global(true), long, value_hint = clap::ValueHint::DirPath, value_name = "DIR")]
/// Build directory, overrides `build.build-dir` in `config.toml`
pub build_dir: Option<PathBuf>,
#[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "BUILD")]
/// build target of the stage0 compiler
pub build: Option<String>,
#[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "HOST", value_parser = target_selection_list)]
/// host targets to build
pub host: Option<TargetSelectionList>,
#[arg(global(true), long, value_hint = clap::ValueHint::Other, value_name = "TARGET", value_parser = target_selection_list)]
/// target targets to build
pub target: Option<TargetSelectionList>,
#[arg(global(true), long, value_name = "PATH")]
/// build paths to exclude
pub exclude: Vec<PathBuf>, // keeping for client backward compatibility
#[arg(global(true), long, value_name = "PATH")]
/// build paths to skip
pub skip: Vec<PathBuf>,
#[arg(global(true), long)]
/// include default paths in addition to the provided ones
pub include_default_paths: bool,
#[arg(global(true), value_hint = clap::ValueHint::Other, long)]
pub rustc_error_format: Option<String>,
#[arg(global(true), long, value_hint = clap::ValueHint::CommandString, value_name = "CMD")]
/// command to run on failure
pub on_fail: Option<String>,
#[arg(global(true), long)]
/// dry run; don't build anything
pub dry_run: bool,
#[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
/// stage to build (indicates compiler to use/test, e.g., stage 0 uses the
/// bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)
pub stage: Option<u32>,
#[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
/// stage(s) to keep without recompiling
/// (pass multiple times to keep e.g., both stages 0 and 1)
pub keep_stage: Vec<u32>,
#[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
/// stage(s) of the standard library to keep without recompiling
/// (pass multiple times to keep e.g., both stages 0 and 1)
pub keep_stage_std: Vec<u32>,
#[arg(global(true), long, value_hint = clap::ValueHint::DirPath, value_name = "DIR")]
/// path to the root of the rust checkout
pub src: Option<PathBuf>,
#[arg(
global(true),
short,
long,
value_hint = clap::ValueHint::Other,
default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get),
value_name = "JOBS"
)]
/// number of jobs to run in parallel
pub jobs: usize,
// This overrides the deny-warnings configuration option,
// which passes -Dwarnings to the compiler invocations.
#[arg(global(true), long)]
#[clap(value_enum, default_value_t=Warnings::Default, value_name = "deny|warn")]
/// if value is deny, will deny warnings
/// if value is warn, will emit warnings
/// otherwise, use the default configured behaviour
pub warnings: Warnings,
#[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "FORMAT")]
/// rustc error format
pub error_format: Option<String>,
#[arg(global(true), long)]
/// use message-format=json
pub json_output: bool,
#[arg(global(true), long, value_name = "STYLE")]
#[clap(value_enum, default_value_t = Color::Auto)]
/// whether to use color in cargo and rustc output
pub color: Color,
/// whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml
#[arg(global(true), long, value_name = "VALUE")]
pub llvm_skip_rebuild: Option<bool>,
/// generate PGO profile with rustc build
#[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
pub rust_profile_generate: Option<String>,
/// use PGO profile for rustc build
#[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
pub rust_profile_use: Option<String>,
/// use PGO profile for LLVM build
#[arg(global(true), value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
pub llvm_profile_use: Option<String>,
// LLVM doesn't support a custom location for generating profile
// information.
//
// llvm_out/build/profiles/ is the location this writes to.
/// generate PGO profile with llvm built for rustc
#[arg(global(true), long)]
pub llvm_profile_generate: bool,
/// Additional reproducible artifacts that should be added to the reproducible artifacts archive.
#[arg(global(true), long)]
pub reproducible_artifact: Vec<String>,
#[arg(global(true))]
/// paths for the subcommand
pub paths: Vec<PathBuf>,
/// override options in config.toml
#[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "section.option=value")]
pub set: Vec<String>,
/// arguments passed to subcommands
#[arg(global(true), last(true), value_name = "ARGS")]
pub free_args: Vec<String>,
}
impl Flags {
pub fn parse(args: &[String]) -> Self {
let first = String::from("x.py");
let it = std::iter::once(&first).chain(args.iter());
// We need to check for `<cmd> -h -v`, in which case we list the paths
#[derive(Parser)]
#[clap(disable_help_flag(true))]
struct HelpVerboseOnly {
#[arg(short, long)]
help: bool,
#[arg(global(true), short, long, action = clap::ArgAction::Count)]
pub verbose: u8,
#[arg(value_enum)]
cmd: Kind,
}
if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) =
HelpVerboseOnly::try_parse_from(it.clone())
{
println!("note: updating submodules before printing available paths");
let config = Config::parse(&[String::from("build")]);
let build = Build::new(config);
let paths = Builder::get_help(&build, subcommand);
if let Some(s) = paths {
println!("{s}");
} else {
panic!("No paths available for subcommand `{}`", subcommand.as_str());
}
crate::exit!(0);
}
Flags::parse_from(it)
}
}
#[derive(Debug, Clone, Default, clap::Subcommand)]
pub enum Subcommand {
#[clap(aliases = ["b"], long_about = "\n
Arguments:
This subcommand accepts a number of paths to directories to the crates
and/or artifacts to compile. For example, for a quick build of a usable
compiler:
./x.py build --stage 1 library/std
This will build a compiler and standard library from the local source code.
Once this is done, build/$ARCH/stage1 contains a usable compiler.
If no arguments are passed then the default artifacts for that stage are
compiled. For example:
./x.py build --stage 0
./x.py build ")]
/// Compile either the compiler or libraries
#[default]
Build,
#[clap(aliases = ["c"], long_about = "\n
Arguments:
This subcommand accepts a number of paths to directories to the crates
and/or artifacts to compile. For example:
./x.py check library/std
If no arguments are passed then many artifacts are checked.")]
/// Compile either the compiler or libraries, using cargo check
Check {
#[arg(long)]
/// Check all targets
all_targets: bool,
},
/// Run Clippy (uses rustup/cargo-installed clippy binary)
#[clap(long_about = "\n
Arguments:
This subcommand accepts a number of paths to directories to the crates
and/or artifacts to run clippy against. For example:
./x.py clippy library/core
./x.py clippy library/core library/proc_macro")]
Clippy {
#[arg(long)]
fix: bool,
/// clippy lints to allow
#[arg(global(true), short = 'A', action = clap::ArgAction::Append, value_name = "LINT")]
allow: Vec<String>,
/// clippy lints to deny
#[arg(global(true), short = 'D', action = clap::ArgAction::Append, value_name = "LINT")]
deny: Vec<String>,
/// clippy lints to warn on
#[arg(global(true), short = 'W', action = clap::ArgAction::Append, value_name = "LINT")]
warn: Vec<String>,
/// clippy lints to forbid
#[arg(global(true), short = 'F', action = clap::ArgAction::Append, value_name = "LINT")]
forbid: Vec<String>,
},
/// Run cargo fix
#[clap(long_about = "\n
Arguments:
This subcommand accepts a number of paths to directories to the crates
and/or artifacts to run `cargo fix` against. For example:
./x.py fix library/core
./x.py fix library/core library/proc_macro")]
Fix,
#[clap(
name = "fmt",
long_about = "\n
Arguments:
This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and
fails if it is not. For example:
./x.py fmt
./x.py fmt --check"
)]
/// Run rustfmt
Format {
/// check formatting instead of applying
#[arg(long)]
check: bool,
},
#[clap(aliases = ["d"], long_about = "\n
Arguments:
This subcommand accepts a number of paths to directories of documentation
to build. For example:
./x.py doc src/doc/book
./x.py doc src/doc/nomicon
./x.py doc src/doc/book library/std
./x.py doc library/std --json
./x.py doc library/std --open
If no arguments are passed then everything is documented:
./x.py doc
./x.py doc --stage 1")]
/// Build documentation
Doc {
#[arg(long)]
/// open the docs in a browser
open: bool,
#[arg(long)]
/// render the documentation in JSON format in addition to the usual HTML format
json: bool,
},
#[clap(aliases = ["t"], long_about = "\n
Arguments:
This subcommand accepts a number of paths to test directories that
should be compiled and run. For example:
./x.py test tests/ui
./x.py test library/std --test-args hash_map
./x.py test library/std --stage 0 --no-doc
./x.py test tests/ui --bless
./x.py test tests/ui --compare-mode next-solver
Note that `test tests/* --stage N` does NOT depend on `build compiler/rustc --stage N`;
just like `build library/std --stage N` it tests the compiler produced by the previous
stage.
Execute tool tests with a tool name argument:
./x.py test tidy
If no arguments are passed then the complete artifacts for that stage are
compiled and tested.
./x.py test
./x.py test --stage 1")]
/// Build and run some test suites
Test {
#[arg(long)]
/// run all tests regardless of failure
no_fail_fast: bool,
#[arg(long, value_name = "SUBSTRING")]
/// skips tests matching SUBSTRING, if supported by test tool. May be passed multiple times
skip: Vec<PathBuf>,
#[arg(long, value_name = "ARGS", allow_hyphen_values(true))]
/// extra arguments to be passed for the test tool being used
/// (e.g. libtest, compiletest or rustdoc)
test_args: Vec<String>,
/// extra options to pass the compiler when running tests
#[arg(long, value_name = "ARGS", allow_hyphen_values(true))]
rustc_args: Vec<String>,
#[arg(long)]
/// do not run doc tests
no_doc: bool,
#[arg(long)]
/// only run doc tests
doc: bool,
#[arg(long)]
/// whether to automatically update stderr/stdout files
bless: bool,
#[arg(long)]
/// comma-separated list of other files types to check (accepts py, py:lint,
/// py:fmt, shell)
extra_checks: Option<String>,
#[arg(long)]
/// rerun tests even if the inputs are unchanged
force_rerun: bool,
#[arg(long)]
/// only run tests that result has been changed
only_modified: bool,
#[arg(long, value_name = "COMPARE MODE")]
/// mode describing what file the actual ui output will be compared to
compare_mode: Option<String>,
#[arg(long, value_name = "check | build | run")]
/// force {check,build,run}-pass tests to this mode.
pass: Option<String>,
#[arg(long, value_name = "auto | always | never")]
/// whether to execute run-* tests
run: Option<String>,
#[arg(long)]
/// enable this to generate a Rustfix coverage file, which is saved in
/// `/<build_base>/rustfix_missing_coverage.txt`
rustfix_coverage: bool,
},
/// Build and run some benchmarks
Bench {
#[arg(long, allow_hyphen_values(true))]
test_args: Vec<String>,
},
/// Clean out build directories
Clean {
#[arg(long)]
/// Clean the entire build directory (not used by default)
all: bool,
#[arg(long, value_name = "N")]
/// Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used.
stage: Option<u32>,
},
/// Build distribution artifacts
Dist,
/// Install distribution artifacts
Install,
#[clap(aliases = ["r"], long_about = "\n
Arguments:
This subcommand accepts a number of paths to tools to build and run. For
example:
./x.py run src/tools/expand-yaml-anchors
At least a tool needs to be called.")]
/// Run tools contained in this repository
Run {
/// arguments for the tool
#[arg(long, allow_hyphen_values(true))]
args: Vec<String>,
},
/// Set up the environment for development
#[clap(long_about = format!(
"\n
x.py setup creates a `config.toml` which changes the defaults for x.py itself,
as well as setting up a git pre-push hook, VS Code config and toolchain link.
Arguments:
This subcommand accepts a 'profile' to use for builds. For example:
./x.py setup library
The profile is optional and you will be prompted interactively if it is not given.
The following profiles are available:
{}
To only set up the git hook, VS Code config or toolchain link, you may use
./x.py setup hook
./x.py setup vscode
./x.py setup link", Profile::all_for_help(" ").trim_end()))]
Setup {
/// Either the profile for `config.toml` or another setup action.
/// May be omitted to set up interactively
#[arg(value_name = "<PROFILE>|hook|vscode|link")]
profile: Option<PathBuf>,
},
/// Suggest a subset of tests to run, based on modified files
#[clap(long_about = "\n")]
Suggest {
/// run suggested tests
#[arg(long)]
run: bool,
},
}
impl Subcommand {
pub fn kind(&self) -> Kind {
match self {
Subcommand::Bench { .. } => Kind::Bench,
Subcommand::Build { .. } => Kind::Build,
Subcommand::Check { .. } => Kind::Check,
Subcommand::Clippy { .. } => Kind::Clippy,
Subcommand::Doc { .. } => Kind::Doc,
Subcommand::Fix { .. } => Kind::Fix,
Subcommand::Format { .. } => Kind::Format,
Subcommand::Test { .. } => Kind::Test,
Subcommand::Clean { .. } => Kind::Clean,
Subcommand::Dist { .. } => Kind::Dist,
Subcommand::Install { .. } => Kind::Install,
Subcommand::Run { .. } => Kind::Run,
Subcommand::Setup { .. } => Kind::Setup,
Subcommand::Suggest { .. } => Kind::Suggest,
}
}
pub fn rustc_args(&self) -> Vec<&str> {
match *self {
Subcommand::Test { ref rustc_args, .. } => {
rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
}
_ => vec![],
}
}
pub fn fail_fast(&self) -> bool {
match *self {
Subcommand::Test { no_fail_fast, .. } => !no_fail_fast,
_ => false,
}
}
pub fn doc_tests(&self) -> DocTests {
match *self {
Subcommand::Test { doc, no_doc, .. } => {
if doc {
DocTests::Only
} else if no_doc {
DocTests::No
} else {
DocTests::Yes
}
}
_ => DocTests::Yes,
}
}
pub fn bless(&self) -> bool {
match *self {
Subcommand::Test { bless, .. } => bless,
_ => false,
}
}
pub fn extra_checks(&self) -> Option<&str> {
match *self {
Subcommand::Test { ref extra_checks, .. } => extra_checks.as_ref().map(String::as_str),
_ => None,
}
}
pub fn only_modified(&self) -> bool {
match *self {
Subcommand::Test { only_modified, .. } => only_modified,
_ => false,
}
}
pub fn force_rerun(&self) -> bool {
match *self {
Subcommand::Test { force_rerun, .. } => force_rerun,
_ => false,
}
}
pub fn rustfix_coverage(&self) -> bool {
match *self {
Subcommand::Test { rustfix_coverage, .. } => rustfix_coverage,
_ => false,
}
}
pub fn compare_mode(&self) -> Option<&str> {
match *self {
Subcommand::Test { ref compare_mode, .. } => compare_mode.as_ref().map(|s| &s[..]),
_ => None,
}
}
pub fn pass(&self) -> Option<&str> {
match *self {
Subcommand::Test { ref pass, .. } => pass.as_ref().map(|s| &s[..]),
_ => None,
}
}
pub fn run(&self) -> Option<&str> {
match *self {
Subcommand::Test { ref run, .. } => run.as_ref().map(|s| &s[..]),
_ => None,
}
}
pub fn open(&self) -> bool {
match *self {
Subcommand::Doc { open, .. } => open,
_ => false,
}
}
pub fn json(&self) -> bool {
match *self {
Subcommand::Doc { json, .. } => json,
_ => false,
}
}
}
/// Returns the shell completion for a given shell, if the result differs from the current
/// content of `path`. If `path` does not exist, always returns `Some`.
pub fn get_completion<G: clap_complete::Generator>(shell: G, path: &Path) -> Option<String> {
let mut cmd = Flags::command();
let current = if !path.exists() {
String::new()
} else {
std::fs::read_to_string(path).unwrap_or_else(|_| {
eprintln!("couldn't read {}", path.display());
crate::exit!(1)
})
};
let mut buf = Vec::new();
clap_complete::generate(shell, &mut cmd, "x.py", &mut buf);
if buf == current.as_bytes() {
return None;
}
Some(String::from_utf8(buf).expect("completion script should be UTF-8"))
}

View File

@ -0,0 +1,4 @@
pub(crate) mod config;
pub(crate) mod flags;
pub use config::*;

View File

@ -11,13 +11,10 @@ use build_helper::ci::CiEnv;
use once_cell::sync::OnceCell;
use xz2::bufread::XzDecoder;
use crate::{
config::RustfmtMetadata,
llvm::detect_llvm_sha,
t,
util::{check_run, exe, program_out_of_date},
Config,
};
use crate::core::build_steps::llvm::detect_llvm_sha;
use crate::core::config::RustfmtMetadata;
use crate::utils::helpers::{check_run, exe, program_out_of_date};
use crate::{t, Config};
static SHOULD_FIX_BINS_AND_DYLIBS: OnceCell<bool> = OnceCell::new();

View File

@ -3,8 +3,8 @@ use std::process::Command;
use serde_derive::Deserialize;
use crate::cache::INTERNER;
use crate::util::output;
use crate::utils::cache::INTERNER;
use crate::utils::helpers::output;
use crate::{t, Build, Crate};
/// For more information, see the output of

View File

@ -0,0 +1,6 @@
pub(crate) mod build_steps;
pub(crate) mod builder;
pub(crate) mod config;
pub(crate) mod download;
pub(crate) mod metadata;
pub(crate) mod sanity;

View File

@ -15,9 +15,9 @@ use std::fs;
use std::path::PathBuf;
use std::process::Command;
use crate::cache::INTERNER;
use crate::config::Target;
use crate::util::output;
use crate::core::config::Target;
use crate::utils::cache::INTERNER;
use crate::utils::helpers::output;
use crate::Build;
pub struct Finder {