2016-05-03 00:16:15 +02:00
|
|
|
//! 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.
|
|
|
|
|
2020-06-13 18:04:06 +02:00
|
|
|
use std::env;
|
2015-11-20 00:20:12 +01:00
|
|
|
use std::path::PathBuf;
|
|
|
|
use std::process;
|
|
|
|
|
2020-09-12 08:32:43 +02:00
|
|
|
use build_helper::t;
|
2017-04-02 18:28:36 +02:00
|
|
|
use getopts::Options;
|
2016-10-21 22:18:09 +02:00
|
|
|
|
2018-12-07 13:21:05 +01:00
|
|
|
use crate::builder::Builder;
|
2020-07-17 16:08:04 +02:00
|
|
|
use crate::config::{Config, TargetSelection};
|
2020-10-05 17:27:42 +02:00
|
|
|
use crate::setup::Profile;
|
2018-12-07 13:21:05 +01:00
|
|
|
use crate::{Build, DocTests};
|
2015-11-20 00:20:12 +01:00
|
|
|
|
2020-11-12 22:23:35 +01:00
|
|
|
pub enum Color {
|
|
|
|
Always,
|
|
|
|
Never,
|
|
|
|
Auto,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Color {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Auto
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::str::FromStr for Color {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
match s.to_lowercase().as_str() {
|
|
|
|
"always" => Ok(Self::Always),
|
|
|
|
"never" => Ok(Self::Never),
|
|
|
|
"auto" => Ok(Self::Auto),
|
|
|
|
_ => Err(()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-03 00:16:15 +02:00
|
|
|
/// Deserialized version of all flags for this compile.
|
2015-11-20 00:20:12 +01:00
|
|
|
pub struct Flags {
|
2018-03-12 00:44:05 +01:00
|
|
|
pub verbose: usize, // number of -v args; each extra -v after the first is passed to Cargo
|
2017-02-16 19:52:56 +01:00
|
|
|
pub on_fail: Option<String>,
|
2015-11-20 00:20:12 +01:00
|
|
|
pub stage: Option<u32>,
|
2018-07-14 18:58:10 +02:00
|
|
|
pub keep_stage: Vec<u32>,
|
2020-09-23 23:25:23 +02:00
|
|
|
pub keep_stage_std: Vec<u32>,
|
2017-07-30 06:12:53 +02:00
|
|
|
|
2020-09-06 18:57:13 +02:00
|
|
|
pub host: Option<Vec<TargetSelection>>,
|
|
|
|
pub target: Option<Vec<TargetSelection>>,
|
2015-11-20 00:20:12 +01:00
|
|
|
pub config: Option<PathBuf>,
|
|
|
|
pub jobs: Option<u32>,
|
2016-10-21 22:18:09 +02:00
|
|
|
pub cmd: Subcommand,
|
2016-11-17 00:02:56 +01:00
|
|
|
pub incremental: bool,
|
2018-02-09 21:40:23 +01:00
|
|
|
pub exclude: Vec<PathBuf>,
|
2020-10-09 19:51:07 +02:00
|
|
|
pub include_default_paths: bool,
|
2018-02-24 23:56:33 +01:00
|
|
|
pub rustc_error_format: Option<String>,
|
2020-03-31 03:21:35 +02:00
|
|
|
pub json_output: bool,
|
2018-03-27 16:06:47 +02:00
|
|
|
pub dry_run: bool,
|
2020-11-12 22:23:35 +01:00
|
|
|
pub color: Color,
|
2018-04-01 17:35:53 +02:00
|
|
|
|
2020-03-06 12:13:55 +01:00
|
|
|
// This overrides the deny-warnings configuration option,
|
2019-07-05 13:24:58 +02:00
|
|
|
// which passes -Dwarnings to the compiler invocations.
|
|
|
|
//
|
2019-09-02 20:24:40 +02:00
|
|
|
// true => deny, false => warn
|
2019-07-05 13:24:58 +02:00
|
|
|
pub deny_warnings: Option<bool>,
|
2020-01-09 22:51:38 +01:00
|
|
|
|
|
|
|
pub llvm_skip_rebuild: Option<bool>,
|
Utilize PGO for rustc linux dist builds
This implements support for applying PGO to the rustc compilation step (not
standard library or any tooling, including rustdoc). Expanding PGO to more tools
is not terribly difficult but will involve more work and greater CI time
commitment.
For the same reason of avoiding greater time commitment, this currently avoids
implementing for platforms outside of x86_64-unknown-linux-gnu, though in
practice it should be quite simple to extend over time to more platforms. The
initial implementation is intentionally minimal here to avoid too much work
investment before we start seeing wins for a subset of Rust users.
The choice of workloads to profile here is somewhat arbitrary, but the general
rationale was to aim for a small set that largely avoided time regressions on
perf.rust-lang.org's full suite of crates. The set chosen is libcore, cargo (and
its dependencies), and a few ad-hoc stress tests from perf.rlo. The stress tests
are arguably the most controversial, but they benefit those cases (avoiding
regressions) and do not really remove wins from other benchmarks.
The primary next step after this PR lands is to implement support for PGO in
LLVM. It is unclear whether we can afford a full LLVM rebuild in CI, though, so
the approach taken there may need to be more staggered. rustc-only PGO seems
well affordable on linux at least, giving us up to 20% wall time wins on some
crates for 15 minutes of extra CI time (1 hour up from 45 minutes).
The PGO data is uploaded to allow others to reuse it if attempting to reproduce
the CI build or potentially, in the future, on other platforms where an
off-by-one strategy is used for dist builds at minimal performance cost.
2020-12-14 19:50:59 +01:00
|
|
|
|
|
|
|
pub rust_profile_use: Option<String>,
|
|
|
|
pub rust_profile_generate: Option<String>,
|
2016-11-17 00:02:56 +01:00
|
|
|
}
|
|
|
|
|
2016-10-21 22:18:09 +02:00
|
|
|
pub enum Subcommand {
|
|
|
|
Build {
|
|
|
|
paths: Vec<PathBuf>,
|
|
|
|
},
|
2018-01-15 18:44:00 +01:00
|
|
|
Check {
|
2020-10-03 01:51:36 +02:00
|
|
|
// Whether to run checking over all targets (e.g., unit / integration
|
|
|
|
// tests).
|
|
|
|
all_targets: bool,
|
2018-01-15 18:44:00 +01:00
|
|
|
paths: Vec<PathBuf>,
|
|
|
|
},
|
2018-12-04 19:26:54 +01:00
|
|
|
Clippy {
|
2020-09-30 02:24:14 +02:00
|
|
|
fix: bool,
|
2018-12-04 19:26:54 +01:00
|
|
|
paths: Vec<PathBuf>,
|
|
|
|
},
|
|
|
|
Fix {
|
|
|
|
paths: Vec<PathBuf>,
|
|
|
|
},
|
2019-10-31 00:56:27 +01:00
|
|
|
Format {
|
|
|
|
check: bool,
|
|
|
|
},
|
2016-10-21 22:18:09 +02:00
|
|
|
Doc {
|
|
|
|
paths: Vec<PathBuf>,
|
2020-05-22 04:48:44 +02:00
|
|
|
open: bool,
|
2016-10-21 22:18:09 +02:00
|
|
|
},
|
|
|
|
Test {
|
|
|
|
paths: Vec<PathBuf>,
|
2018-05-16 17:18:19 +02:00
|
|
|
/// Whether to automatically update stderr/stdout files
|
|
|
|
bless: bool,
|
2018-05-29 00:44:33 +02:00
|
|
|
compare_mode: Option<String>,
|
2019-06-12 00:43:44 +02:00
|
|
|
pass: Option<String>,
|
2016-10-21 22:18:09 +02:00
|
|
|
test_args: Vec<String>,
|
2018-01-18 23:44:41 +01:00
|
|
|
rustc_args: Vec<String>,
|
2017-06-27 21:37:24 +02:00
|
|
|
fail_fast: bool,
|
2018-05-05 21:30:42 +02:00
|
|
|
doc_tests: DocTests,
|
2019-03-24 14:06:47 +01:00
|
|
|
rustfix_coverage: bool,
|
2016-10-21 22:18:09 +02:00
|
|
|
},
|
2016-11-25 22:13:59 +01:00
|
|
|
Bench {
|
|
|
|
paths: Vec<PathBuf>,
|
|
|
|
test_args: Vec<String>,
|
|
|
|
},
|
2017-09-20 19:14:19 +02:00
|
|
|
Clean {
|
|
|
|
all: bool,
|
|
|
|
},
|
2016-10-21 22:18:09 +02:00
|
|
|
Dist {
|
2017-01-01 02:42:40 +01:00
|
|
|
paths: Vec<PathBuf>,
|
2017-05-18 22:48:14 +02:00
|
|
|
},
|
|
|
|
Install {
|
|
|
|
paths: Vec<PathBuf>,
|
2016-10-21 22:18:09 +02:00
|
|
|
},
|
2019-11-26 12:06:30 +01:00
|
|
|
Run {
|
|
|
|
paths: Vec<PathBuf>,
|
|
|
|
},
|
2020-09-12 08:32:43 +02:00
|
|
|
Setup {
|
2020-10-05 17:27:42 +02:00
|
|
|
profile: Profile,
|
2020-09-12 08:32:43 +02:00
|
|
|
},
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
|
2017-07-30 06:12:53 +02:00
|
|
|
impl Default for Subcommand {
|
|
|
|
fn default() -> Subcommand {
|
2019-12-22 23:42:04 +01:00
|
|
|
Subcommand::Build { paths: vec![PathBuf::from("nowhere")] }
|
2017-07-30 06:12:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-20 00:20:12 +01:00
|
|
|
impl Flags {
|
|
|
|
pub fn parse(args: &[String]) -> Flags {
|
2019-12-22 23:42:04 +01:00
|
|
|
let mut subcommand_help = String::from(
|
|
|
|
"\
|
2017-04-01 23:48:03 +02:00
|
|
|
Usage: x.py <subcommand> [options] [<paths>...]
|
|
|
|
|
|
|
|
Subcommands:
|
2020-05-05 00:31:37 +02:00
|
|
|
build, b Compile either the compiler or libraries
|
|
|
|
check, c Compile either the compiler or libraries, using cargo check
|
2020-01-22 01:02:32 +01:00
|
|
|
clippy Run clippy (uses rustup/cargo-installed clippy binary)
|
2018-12-04 19:26:54 +01:00
|
|
|
fix Run cargo fix
|
2019-10-31 00:56:27 +01:00
|
|
|
fmt Run rustfmt
|
2020-05-05 00:31:37 +02:00
|
|
|
test, t Build and run some test suites
|
2017-04-01 23:48:03 +02:00
|
|
|
bench Build and run some benchmarks
|
|
|
|
doc Build documentation
|
|
|
|
clean Clean out build directories
|
2017-05-18 22:48:14 +02:00
|
|
|
dist Build distribution artifacts
|
|
|
|
install Install distribution artifacts
|
2020-05-05 00:31:37 +02:00
|
|
|
run, r Run tools contained in this repository
|
2020-10-13 00:54:49 +02:00
|
|
|
setup Create a config.toml (making it easier to use `x.py` itself)
|
2017-04-01 23:48:03 +02:00
|
|
|
|
2019-12-22 23:42:04 +01:00
|
|
|
To learn more about a subcommand, run `./x.py <subcommand> -h`",
|
2018-05-30 19:33:43 +02:00
|
|
|
);
|
2017-04-01 23:48:03 +02:00
|
|
|
|
2015-11-20 00:20:12 +01:00
|
|
|
let mut opts = Options::new();
|
2017-04-01 23:48:03 +02:00
|
|
|
// Options common to all subcommands
|
2016-11-17 00:02:56 +01:00
|
|
|
opts.optflagmulti("v", "verbose", "use verbose output (-vv for very verbose)");
|
|
|
|
opts.optflag("i", "incremental", "use incremental compilation");
|
2015-11-20 00:20:12 +01:00
|
|
|
opts.optopt("", "config", "TOML configuration file for build", "FILE");
|
2016-10-21 22:18:09 +02:00
|
|
|
opts.optopt("", "build", "build target of the stage0 compiler", "BUILD");
|
2015-11-20 00:20:12 +01:00
|
|
|
opts.optmulti("", "host", "host targets to build", "HOST");
|
2016-10-21 22:18:09 +02:00
|
|
|
opts.optmulti("", "target", "target targets to build", "TARGET");
|
2018-02-09 21:40:23 +01:00
|
|
|
opts.optmulti("", "exclude", "build paths to exclude", "PATH");
|
2020-10-09 19:51:07 +02:00
|
|
|
opts.optflag(
|
|
|
|
"",
|
|
|
|
"include-default-paths",
|
|
|
|
"include default paths in addition to the provided ones",
|
|
|
|
);
|
2017-02-16 19:52:56 +01:00
|
|
|
opts.optopt("", "on-fail", "command to run on failure", "CMD");
|
2018-03-27 16:06:47 +02:00
|
|
|
opts.optflag("", "dry-run", "dry run; don't build anything");
|
2019-12-22 23:42:04 +01:00
|
|
|
opts.optopt(
|
|
|
|
"",
|
|
|
|
"stage",
|
2018-11-27 03:59:49 +01:00
|
|
|
"stage to build (indicates compiler to use/test, e.g., stage 0 uses the \
|
2018-07-30 12:52:01 +02:00
|
|
|
bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)",
|
2019-12-22 23:42:04 +01:00
|
|
|
"N",
|
|
|
|
);
|
|
|
|
opts.optmulti(
|
|
|
|
"",
|
|
|
|
"keep-stage",
|
|
|
|
"stage(s) to keep without recompiling \
|
|
|
|
(pass multiple times to keep e.g., both stages 0 and 1)",
|
|
|
|
"N",
|
|
|
|
);
|
2020-09-23 23:25:23 +02:00
|
|
|
opts.optmulti(
|
|
|
|
"",
|
|
|
|
"keep-stage-std",
|
|
|
|
"stage(s) of the standard library to keep without recompiling \
|
|
|
|
(pass multiple times to keep e.g., both stages 0 and 1)",
|
|
|
|
"N",
|
|
|
|
);
|
2016-10-21 22:18:09 +02:00
|
|
|
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
|
2020-06-15 21:02:57 +02:00
|
|
|
let j_msg = format!(
|
|
|
|
"number of jobs to run in parallel; \
|
|
|
|
defaults to {} (this host's logical CPU count)",
|
|
|
|
num_cpus::get()
|
|
|
|
);
|
|
|
|
opts.optopt("j", "jobs", &j_msg, "JOBS");
|
2015-11-20 00:20:12 +01:00
|
|
|
opts.optflag("h", "help", "print this help message");
|
2018-05-30 19:33:43 +02:00
|
|
|
opts.optopt(
|
|
|
|
"",
|
|
|
|
"warnings",
|
|
|
|
"if value is deny, will deny warnings, otherwise use default",
|
|
|
|
"VALUE",
|
|
|
|
);
|
2018-02-26 23:07:24 +01:00
|
|
|
opts.optopt("", "error-format", "rustc error format", "FORMAT");
|
2020-03-31 03:21:35 +02:00
|
|
|
opts.optflag("", "json-output", "use message-format=json");
|
2020-11-12 22:23:35 +01:00
|
|
|
opts.optopt("", "color", "whether to use color in cargo and rustc output", "STYLE");
|
2020-01-09 22:19:33 +01:00
|
|
|
opts.optopt(
|
|
|
|
"",
|
|
|
|
"llvm-skip-rebuild",
|
|
|
|
"whether rebuilding llvm should be skipped \
|
|
|
|
a VALUE of TRUE indicates that llvm will not be rebuilt \
|
|
|
|
VALUE overrides the skip-rebuild option in config.toml.",
|
|
|
|
"VALUE",
|
|
|
|
);
|
Utilize PGO for rustc linux dist builds
This implements support for applying PGO to the rustc compilation step (not
standard library or any tooling, including rustdoc). Expanding PGO to more tools
is not terribly difficult but will involve more work and greater CI time
commitment.
For the same reason of avoiding greater time commitment, this currently avoids
implementing for platforms outside of x86_64-unknown-linux-gnu, though in
practice it should be quite simple to extend over time to more platforms. The
initial implementation is intentionally minimal here to avoid too much work
investment before we start seeing wins for a subset of Rust users.
The choice of workloads to profile here is somewhat arbitrary, but the general
rationale was to aim for a small set that largely avoided time regressions on
perf.rust-lang.org's full suite of crates. The set chosen is libcore, cargo (and
its dependencies), and a few ad-hoc stress tests from perf.rlo. The stress tests
are arguably the most controversial, but they benefit those cases (avoiding
regressions) and do not really remove wins from other benchmarks.
The primary next step after this PR lands is to implement support for PGO in
LLVM. It is unclear whether we can afford a full LLVM rebuild in CI, though, so
the approach taken there may need to be more staggered. rustc-only PGO seems
well affordable on linux at least, giving us up to 20% wall time wins on some
crates for 15 minutes of extra CI time (1 hour up from 45 minutes).
The PGO data is uploaded to allow others to reuse it if attempting to reproduce
the CI build or potentially, in the future, on other platforms where an
off-by-one strategy is used for dist builds at minimal performance cost.
2020-12-14 19:50:59 +01:00
|
|
|
opts.optopt("", "rust-profile-generate", "rustc error format", "FORMAT");
|
|
|
|
opts.optopt("", "rust-profile-use", "rustc error format", "FORMAT");
|
2015-11-20 00:20:12 +01:00
|
|
|
|
2017-04-02 07:16:46 +02:00
|
|
|
// We can't use getopt to parse the options until we have completed specifying which
|
|
|
|
// options are valid, but under the current implementation, some options are conditional on
|
|
|
|
// the subcommand. Therefore we must manually identify the subcommand first, so that we can
|
|
|
|
// complete the definition of the options. Then we can use the getopt::Matches object from
|
|
|
|
// there on out.
|
2018-05-30 19:33:43 +02:00
|
|
|
let subcommand = args.iter().find(|&s| {
|
2017-06-21 19:15:49 +02:00
|
|
|
(s == "build")
|
2020-05-05 00:31:37 +02:00
|
|
|
|| (s == "b")
|
2018-05-30 19:33:43 +02:00
|
|
|
|| (s == "check")
|
2020-05-05 00:31:37 +02:00
|
|
|
|| (s == "c")
|
2018-12-04 19:26:54 +01:00
|
|
|
|| (s == "clippy")
|
|
|
|
|| (s == "fix")
|
2019-10-31 00:56:27 +01:00
|
|
|
|| (s == "fmt")
|
2018-05-30 19:33:43 +02:00
|
|
|
|| (s == "test")
|
2020-05-05 00:31:37 +02:00
|
|
|
|| (s == "t")
|
2018-05-30 19:33:43 +02:00
|
|
|
|| (s == "bench")
|
|
|
|
|| (s == "doc")
|
|
|
|
|| (s == "clean")
|
|
|
|
|| (s == "dist")
|
|
|
|
|| (s == "install")
|
2019-11-26 12:06:30 +01:00
|
|
|
|| (s == "run")
|
2020-05-05 00:31:37 +02:00
|
|
|
|| (s == "r")
|
2020-09-12 08:32:43 +02:00
|
|
|
|| (s == "setup")
|
2018-05-30 19:33:43 +02:00
|
|
|
});
|
2017-06-21 19:15:49 +02:00
|
|
|
let subcommand = match subcommand {
|
2017-04-02 07:16:46 +02:00
|
|
|
Some(s) => s,
|
|
|
|
None => {
|
2017-10-25 23:03:07 +02:00
|
|
|
// No or an invalid subcommand -- show the general usage and subcommand help
|
|
|
|
// An exit code will be 0 when no subcommand is given, and 1 in case of an invalid
|
|
|
|
// subcommand.
|
2017-04-01 23:48:03 +02:00
|
|
|
println!("{}\n", subcommand_help);
|
2017-10-25 23:03:07 +02:00
|
|
|
let exit_code = if args.is_empty() { 0 } else { 1 };
|
|
|
|
process::exit(exit_code);
|
2017-04-01 23:48:03 +02:00
|
|
|
}
|
|
|
|
};
|
2017-03-31 06:18:27 +02:00
|
|
|
|
2017-04-04 03:15:31 +02:00
|
|
|
// Some subcommands get extra options
|
|
|
|
match subcommand.as_str() {
|
2020-05-05 00:31:37 +02:00
|
|
|
"test" | "t" => {
|
2017-06-02 18:27:44 +02:00
|
|
|
opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
|
2020-10-22 19:36:16 +02:00
|
|
|
opts.optmulti(
|
|
|
|
"",
|
|
|
|
"test-args",
|
|
|
|
"extra arguments to be passed for the test tool being used \
|
|
|
|
(e.g. libtest, compiletest or rustdoc)",
|
|
|
|
"ARGS",
|
|
|
|
);
|
2018-01-18 23:44:41 +01:00
|
|
|
opts.optmulti(
|
|
|
|
"",
|
|
|
|
"rustc-args",
|
|
|
|
"extra options to pass the compiler when running tests",
|
|
|
|
"ARGS",
|
|
|
|
);
|
2018-05-05 18:04:06 +02:00
|
|
|
opts.optflag("", "no-doc", "do not run doc tests");
|
|
|
|
opts.optflag("", "doc", "only run doc tests");
|
2019-12-22 23:42:04 +01:00
|
|
|
opts.optflag("", "bless", "update all stderr/stdout files of failing ui tests");
|
2018-05-30 19:33:43 +02:00
|
|
|
opts.optopt(
|
|
|
|
"",
|
|
|
|
"compare-mode",
|
|
|
|
"mode describing what file the actual ui output will be compared to",
|
|
|
|
"COMPARE MODE",
|
|
|
|
);
|
2019-06-12 00:43:44 +02:00
|
|
|
opts.optopt(
|
|
|
|
"",
|
|
|
|
"pass",
|
|
|
|
"force {check,build,run}-pass tests to this mode.",
|
2019-12-22 23:42:04 +01:00
|
|
|
"check | build | run",
|
2019-06-12 00:43:44 +02:00
|
|
|
);
|
2019-03-24 14:06:47 +01:00
|
|
|
opts.optflag(
|
|
|
|
"",
|
|
|
|
"rustfix-coverage",
|
|
|
|
"enable this to generate a Rustfix coverage file, which is saved in \
|
2019-03-25 22:48:35 +01:00
|
|
|
`/<build_base>/rustfix_missing_coverage.txt`",
|
2019-03-24 14:06:47 +01:00
|
|
|
);
|
2018-05-30 19:33:43 +02:00
|
|
|
}
|
2020-10-06 21:04:14 +02:00
|
|
|
"check" | "c" => {
|
2020-10-03 01:51:36 +02:00
|
|
|
opts.optflag("", "all-targets", "Check all targets");
|
|
|
|
}
|
2018-05-30 19:33:43 +02:00
|
|
|
"bench" => {
|
|
|
|
opts.optmulti("", "test-args", "extra arguments", "ARGS");
|
|
|
|
}
|
2020-09-30 02:24:14 +02:00
|
|
|
"clippy" => {
|
|
|
|
opts.optflag("", "fix", "automatically apply lint suggestions");
|
|
|
|
}
|
2020-05-22 04:48:44 +02:00
|
|
|
"doc" => {
|
|
|
|
opts.optflag("", "open", "open the docs in a browser");
|
|
|
|
}
|
2018-05-30 19:33:43 +02:00
|
|
|
"clean" => {
|
|
|
|
opts.optflag("", "all", "clean all build artifacts");
|
|
|
|
}
|
2019-10-31 00:56:27 +01:00
|
|
|
"fmt" => {
|
|
|
|
opts.optflag("", "check", "check formatting instead of applying.");
|
|
|
|
}
|
2018-05-30 19:33:43 +02:00
|
|
|
_ => {}
|
2017-04-04 03:15:31 +02:00
|
|
|
};
|
|
|
|
|
2020-09-16 19:31:20 +02:00
|
|
|
// fn usage()
|
|
|
|
let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! {
|
|
|
|
let mut extra_help = String::new();
|
|
|
|
|
|
|
|
// All subcommands except `clean` can have an optional "Available paths" section
|
|
|
|
if verbose {
|
|
|
|
let config = Config::parse(&["build".to_string()]);
|
|
|
|
let build = Build::new(config);
|
|
|
|
|
|
|
|
let maybe_rules_help = Builder::get_help(&build, subcommand.as_str());
|
|
|
|
extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str());
|
|
|
|
} else if !(subcommand.as_str() == "clean" || subcommand.as_str() == "fmt") {
|
|
|
|
extra_help.push_str(
|
|
|
|
format!("Run `./x.py {} -h -v` to see a list of available paths.", subcommand)
|
|
|
|
.as_str(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("{}", opts.usage(subcommand_help));
|
|
|
|
if !extra_help.is_empty() {
|
|
|
|
println!("{}", extra_help);
|
|
|
|
}
|
|
|
|
process::exit(exit_code);
|
|
|
|
};
|
|
|
|
|
2017-04-04 03:15:31 +02:00
|
|
|
// Done specifying what options are possible, so do the getopts parsing
|
2021-02-16 00:30:06 +01:00
|
|
|
let matches = opts.parse(args).unwrap_or_else(|e| {
|
2017-04-04 03:15:31 +02:00
|
|
|
// Invalid argument/option format
|
|
|
|
println!("\n{}\n", e);
|
2020-09-16 19:31:20 +02:00
|
|
|
usage(1, &opts, false, &subcommand_help);
|
2017-04-04 03:15:31 +02:00
|
|
|
});
|
2020-09-16 19:31:20 +02:00
|
|
|
|
2017-04-04 03:15:31 +02:00
|
|
|
// Extra sanity check to make sure we didn't hit this crazy corner case:
|
|
|
|
//
|
|
|
|
// ./x.py --frobulate clean build
|
|
|
|
// ^-- option ^ ^- actual subcommand
|
|
|
|
// \_ arg to option could be mistaken as subcommand
|
|
|
|
let mut pass_sanity_check = true;
|
|
|
|
match matches.free.get(0) {
|
|
|
|
Some(check_subcommand) => {
|
2017-06-22 01:03:14 +02:00
|
|
|
if check_subcommand != subcommand {
|
2017-04-04 03:15:31 +02:00
|
|
|
pass_sanity_check = false;
|
|
|
|
}
|
2018-05-30 19:33:43 +02:00
|
|
|
}
|
2017-04-04 03:15:31 +02:00
|
|
|
None => {
|
|
|
|
pass_sanity_check = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !pass_sanity_check {
|
|
|
|
println!("{}\n", subcommand_help);
|
2018-05-30 19:33:43 +02:00
|
|
|
println!(
|
|
|
|
"Sorry, I couldn't figure out which subcommand you were trying to specify.\n\
|
|
|
|
You may need to move some options to after the subcommand.\n"
|
|
|
|
);
|
2017-04-04 03:15:31 +02:00
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
// Extra help text for some commands
|
2017-04-01 23:48:03 +02:00
|
|
|
match subcommand.as_str() {
|
2020-05-05 00:31:37 +02:00
|
|
|
"build" | "b" => {
|
2018-05-30 19:33:43 +02:00
|
|
|
subcommand_help.push_str(
|
|
|
|
"\n
|
2016-10-21 22:18:09 +02:00
|
|
|
Arguments:
|
2017-04-02 07:16:46 +02:00
|
|
|
This subcommand accepts a number of paths to directories to the crates
|
2017-03-31 06:18:27 +02:00
|
|
|
and/or artifacts to compile. For example:
|
2016-10-21 22:18:09 +02:00
|
|
|
|
2020-06-12 04:31:49 +02:00
|
|
|
./x.py build library/core
|
|
|
|
./x.py build library/core library/proc_macro
|
|
|
|
./x.py build library/std --stage 1
|
2016-10-21 22:18:09 +02:00
|
|
|
|
|
|
|
If no arguments are passed then the complete artifacts for that stage are
|
|
|
|
also compiled.
|
|
|
|
|
|
|
|
./x.py build
|
|
|
|
./x.py build --stage 1
|
|
|
|
|
2017-06-08 07:08:48 +02:00
|
|
|
For a quick build of a usable compiler, you can pass:
|
2016-10-21 22:18:09 +02:00
|
|
|
|
2020-06-12 04:31:49 +02:00
|
|
|
./x.py build --stage 1 library/test
|
2017-06-06 23:26:56 +02:00
|
|
|
|
2018-07-30 12:57:20 +02:00
|
|
|
This will first build everything once (like `--stage 0` without further
|
2017-06-06 23:26:56 +02:00
|
|
|
arguments would), and then use the compiler built in stage 0 to build
|
2020-06-12 04:31:49 +02:00
|
|
|
library/test and its dependencies.
|
2018-05-30 19:33:43 +02:00
|
|
|
Once this is done, build/$ARCH/stage1 contains a usable compiler.",
|
|
|
|
);
|
2018-01-15 18:44:00 +01:00
|
|
|
}
|
2020-05-05 00:31:37 +02:00
|
|
|
"check" | "c" => {
|
2018-05-30 19:33:43 +02:00
|
|
|
subcommand_help.push_str(
|
|
|
|
"\n
|
2018-01-15 18:44:00 +01:00
|
|
|
Arguments:
|
|
|
|
This subcommand accepts a number of paths to directories to the crates
|
|
|
|
and/or artifacts to compile. For example:
|
|
|
|
|
2020-06-12 04:31:49 +02:00
|
|
|
./x.py check library/core
|
|
|
|
./x.py check library/core library/proc_macro
|
2018-01-15 18:44:00 +01:00
|
|
|
|
|
|
|
If no arguments are passed then the complete artifacts are compiled: std, test, and rustc. Note
|
|
|
|
also that since we use `cargo check`, by default this will automatically enable incremental
|
|
|
|
compilation, so there's no need to pass it separately, though it won't hurt. We also completely
|
|
|
|
ignore the stage passed, as there's no way to compile in non-stage 0 without actually building
|
2018-05-30 19:33:43 +02:00
|
|
|
the compiler.",
|
|
|
|
);
|
2017-04-01 23:48:03 +02:00
|
|
|
}
|
2018-12-04 19:26:54 +01:00
|
|
|
"clippy" => {
|
|
|
|
subcommand_help.push_str(
|
|
|
|
"\n
|
|
|
|
Arguments:
|
|
|
|
This subcommand accepts a number of paths to directories to the crates
|
|
|
|
and/or artifacts to run clippy against. For example:
|
|
|
|
|
2020-06-12 04:31:49 +02:00
|
|
|
./x.py clippy library/core
|
|
|
|
./x.py clippy library/core library/proc_macro",
|
2018-12-04 19:26:54 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
"fix" => {
|
|
|
|
subcommand_help.push_str(
|
|
|
|
"\n
|
|
|
|
Arguments:
|
|
|
|
This subcommand accepts a number of paths to directories to the crates
|
|
|
|
and/or artifacts to run `cargo fix` against. For example:
|
|
|
|
|
2020-06-12 04:31:49 +02:00
|
|
|
./x.py fix library/core
|
|
|
|
./x.py fix library/core library/proc_macro",
|
2018-12-04 19:26:54 +01:00
|
|
|
);
|
|
|
|
}
|
2019-10-31 00:56:27 +01:00
|
|
|
"fmt" => {
|
|
|
|
subcommand_help.push_str(
|
|
|
|
"\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",
|
|
|
|
);
|
|
|
|
}
|
2020-05-05 00:31:37 +02:00
|
|
|
"test" | "t" => {
|
2018-05-30 19:33:43 +02:00
|
|
|
subcommand_help.push_str(
|
|
|
|
"\n
|
2016-10-21 22:18:09 +02:00
|
|
|
Arguments:
|
2020-03-10 03:04:59 +01:00
|
|
|
This subcommand accepts a number of paths to test directories that
|
2017-03-31 06:18:27 +02:00
|
|
|
should be compiled and run. For example:
|
2016-10-21 22:18:09 +02:00
|
|
|
|
2019-07-27 01:26:27 +02:00
|
|
|
./x.py test src/test/ui
|
2020-06-12 04:31:49 +02:00
|
|
|
./x.py test library/std --test-args hash_map
|
|
|
|
./x.py test library/std --stage 0 --no-doc
|
2018-05-16 18:17:29 +02:00
|
|
|
./x.py test src/test/ui --bless
|
2018-05-29 00:44:33 +02:00
|
|
|
./x.py test src/test/ui --compare-mode nll
|
2016-10-21 22:18:09 +02:00
|
|
|
|
2020-08-28 05:58:48 +02:00
|
|
|
Note that `test src/test/* --stage N` does NOT depend on `build compiler/rustc --stage N`;
|
2020-06-12 04:31:49 +02:00
|
|
|
just like `build library/std --stage N` it tests the compiler produced by the previous
|
2018-07-30 12:57:20 +02:00
|
|
|
stage.
|
|
|
|
|
2020-03-10 03:04:59 +01:00
|
|
|
Execute tool tests with a tool name argument:
|
|
|
|
|
|
|
|
./x.py test tidy
|
|
|
|
|
2016-10-21 22:18:09 +02:00
|
|
|
If no arguments are passed then the complete artifacts for that stage are
|
|
|
|
compiled and tested.
|
|
|
|
|
|
|
|
./x.py test
|
2018-05-30 19:33:43 +02:00
|
|
|
./x.py test --stage 1",
|
|
|
|
);
|
2017-04-01 23:48:03 +02:00
|
|
|
}
|
|
|
|
"doc" => {
|
2018-05-30 19:33:43 +02:00
|
|
|
subcommand_help.push_str(
|
|
|
|
"\n
|
2016-10-21 22:18:09 +02:00
|
|
|
Arguments:
|
2017-03-31 06:18:27 +02:00
|
|
|
This subcommand accepts a number of paths to directories of documentation
|
|
|
|
to build. For example:
|
2016-10-21 22:18:09 +02:00
|
|
|
|
|
|
|
./x.py doc src/doc/book
|
|
|
|
./x.py doc src/doc/nomicon
|
2020-06-12 04:31:49 +02:00
|
|
|
./x.py doc src/doc/book library/std
|
|
|
|
./x.py doc library/std --open
|
2016-10-21 22:18:09 +02:00
|
|
|
|
|
|
|
If no arguments are passed then everything is documented:
|
|
|
|
|
|
|
|
./x.py doc
|
2018-05-30 19:33:43 +02:00
|
|
|
./x.py doc --stage 1",
|
|
|
|
);
|
2016-10-21 22:18:09 +02:00
|
|
|
}
|
2020-05-05 00:31:37 +02:00
|
|
|
"run" | "r" => {
|
2019-11-26 12:06:30 +01:00
|
|
|
subcommand_help.push_str(
|
|
|
|
"\n
|
|
|
|
Arguments:
|
|
|
|
This subcommand accepts a number of paths to tools to build and run. For
|
|
|
|
example:
|
|
|
|
|
2020-07-28 15:36:56 +02:00
|
|
|
./x.py run src/tools/expand-yaml-anchors
|
2019-11-26 12:06:30 +01:00
|
|
|
|
|
|
|
At least a tool needs to be called.",
|
|
|
|
);
|
|
|
|
}
|
2020-09-12 08:32:43 +02:00
|
|
|
"setup" => {
|
2020-10-13 00:54:49 +02:00
|
|
|
subcommand_help.push_str(&format!(
|
2020-09-12 08:32:43 +02:00
|
|
|
"\n
|
2020-10-13 00:54:49 +02:00
|
|
|
x.py setup creates a `config.toml` which changes the defaults for x.py itself.
|
|
|
|
|
2020-09-12 08:32:43 +02:00
|
|
|
Arguments:
|
|
|
|
This subcommand accepts a 'profile' to use for builds. For example:
|
|
|
|
|
|
|
|
./x.py setup library
|
|
|
|
|
2020-10-13 00:54:49 +02:00
|
|
|
The profile is optional and you will be prompted interactively if it is not given.
|
|
|
|
The following profiles are available:
|
|
|
|
|
|
|
|
{}",
|
|
|
|
Profile::all_for_help(" ").trim_end()
|
|
|
|
));
|
2020-09-12 08:32:43 +02:00
|
|
|
}
|
2018-05-30 19:33:43 +02:00
|
|
|
_ => {}
|
2015-11-20 00:20:12 +01:00
|
|
|
};
|
2017-04-02 07:16:46 +02:00
|
|
|
// Get any optional paths which occur after the subcommand
|
2020-09-12 08:32:43 +02:00
|
|
|
let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
|
2017-04-02 07:16:46 +02:00
|
|
|
|
2020-06-13 18:04:06 +02:00
|
|
|
let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
|
2020-09-16 19:31:20 +02:00
|
|
|
let verbose = matches.opt_present("verbose");
|
2016-10-21 22:18:09 +02:00
|
|
|
|
2017-04-01 23:48:03 +02:00
|
|
|
// User passed in -h/--help?
|
|
|
|
if matches.opt_present("help") {
|
2020-09-16 19:31:20 +02:00
|
|
|
usage(0, &opts, verbose, &subcommand_help);
|
2017-04-01 23:48:03 +02:00
|
|
|
}
|
2016-10-21 22:18:09 +02:00
|
|
|
|
2017-04-01 23:48:03 +02:00
|
|
|
let cmd = match subcommand.as_str() {
|
2020-05-05 00:31:37 +02:00
|
|
|
"build" | "b" => Subcommand::Build { paths },
|
2020-10-03 01:51:36 +02:00
|
|
|
"check" | "c" => {
|
|
|
|
Subcommand::Check { paths, all_targets: matches.opt_present("all-targets") }
|
|
|
|
}
|
2020-09-30 02:24:14 +02:00
|
|
|
"clippy" => Subcommand::Clippy { paths, fix: matches.opt_present("fix") },
|
2018-12-04 19:26:54 +01:00
|
|
|
"fix" => Subcommand::Fix { paths },
|
2020-05-05 00:31:37 +02:00
|
|
|
"test" | "t" => Subcommand::Test {
|
2018-05-30 19:33:43 +02:00
|
|
|
paths,
|
|
|
|
bless: matches.opt_present("bless"),
|
|
|
|
compare_mode: matches.opt_str("compare-mode"),
|
2019-06-12 00:43:44 +02:00
|
|
|
pass: matches.opt_str("pass"),
|
2018-05-30 19:33:43 +02:00
|
|
|
test_args: matches.opt_strs("test-args"),
|
|
|
|
rustc_args: matches.opt_strs("rustc-args"),
|
|
|
|
fail_fast: !matches.opt_present("no-fail-fast"),
|
2019-03-24 14:06:47 +01:00
|
|
|
rustfix_coverage: matches.opt_present("rustfix-coverage"),
|
2018-05-30 19:33:43 +02:00
|
|
|
doc_tests: if matches.opt_present("doc") {
|
|
|
|
DocTests::Only
|
|
|
|
} else if matches.opt_present("no-doc") {
|
|
|
|
DocTests::No
|
|
|
|
} else {
|
|
|
|
DocTests::Yes
|
|
|
|
},
|
|
|
|
},
|
2019-12-22 23:42:04 +01:00
|
|
|
"bench" => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
|
2020-05-22 04:48:44 +02:00
|
|
|
"doc" => Subcommand::Doc { paths, open: matches.opt_present("open") },
|
2016-10-21 22:18:09 +02:00
|
|
|
"clean" => {
|
2018-10-26 16:23:02 +02:00
|
|
|
if !paths.is_empty() {
|
2017-09-20 20:31:59 +02:00
|
|
|
println!("\nclean does not take a path argument\n");
|
2020-09-16 19:31:20 +02:00
|
|
|
usage(1, &opts, verbose, &subcommand_help);
|
2016-10-21 22:18:09 +02:00
|
|
|
}
|
2017-09-20 19:14:19 +02:00
|
|
|
|
2019-12-22 23:42:04 +01:00
|
|
|
Subcommand::Clean { all: matches.opt_present("all") }
|
2019-10-31 00:56:27 +01:00
|
|
|
}
|
2019-12-22 23:42:04 +01:00
|
|
|
"fmt" => Subcommand::Format { check: matches.opt_present("check") },
|
2018-05-30 19:33:43 +02:00
|
|
|
"dist" => Subcommand::Dist { paths },
|
|
|
|
"install" => Subcommand::Install { paths },
|
2020-05-05 00:31:37 +02:00
|
|
|
"run" | "r" => {
|
2019-11-26 12:06:30 +01:00
|
|
|
if paths.is_empty() {
|
|
|
|
println!("\nrun requires at least a path!\n");
|
2020-09-16 19:31:20 +02:00
|
|
|
usage(1, &opts, verbose, &subcommand_help);
|
2019-11-26 12:06:30 +01:00
|
|
|
}
|
|
|
|
Subcommand::Run { paths }
|
|
|
|
}
|
2020-09-12 08:32:43 +02:00
|
|
|
"setup" => {
|
2020-10-05 17:27:42 +02:00
|
|
|
let profile = if paths.len() > 1 {
|
2020-09-12 08:32:43 +02:00
|
|
|
println!("\nat most one profile can be passed to setup\n");
|
|
|
|
usage(1, &opts, verbose, &subcommand_help)
|
|
|
|
} else if let Some(path) = paths.pop() {
|
2020-10-05 17:27:42 +02:00
|
|
|
let profile_string = t!(path.into_os_string().into_string().map_err(
|
|
|
|
|path| format!("{} is not a valid UTF8 string", path.to_string_lossy())
|
|
|
|
));
|
|
|
|
|
2020-10-05 18:03:54 +02:00
|
|
|
profile_string.parse().unwrap_or_else(|err| {
|
|
|
|
eprintln!("error: {}", err);
|
2020-10-05 17:55:14 +02:00
|
|
|
eprintln!("help: the available profiles are:");
|
2020-10-13 01:07:52 +02:00
|
|
|
eprint!("{}", Profile::all_for_help("- "));
|
2020-10-05 17:55:14 +02:00
|
|
|
std::process::exit(1);
|
|
|
|
})
|
2020-09-12 08:32:43 +02:00
|
|
|
} else {
|
|
|
|
t!(crate::setup::interactive_path())
|
|
|
|
};
|
2020-10-05 17:27:42 +02:00
|
|
|
Subcommand::Setup { profile }
|
2020-09-12 08:32:43 +02:00
|
|
|
}
|
2017-03-31 06:18:27 +02:00
|
|
|
_ => {
|
2020-09-16 19:31:20 +02:00
|
|
|
usage(1, &opts, verbose, &subcommand_help);
|
2016-10-21 22:18:09 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-05-13 17:32:43 +02:00
|
|
|
if let Subcommand::Check { .. } = &cmd {
|
2020-09-23 23:25:23 +02:00
|
|
|
if matches.opt_str("keep-stage").is_some()
|
|
|
|
|| matches.opt_str("keep-stage-std").is_some()
|
|
|
|
{
|
2021-01-16 03:43:23 +01:00
|
|
|
println!("--keep-stage not yet supported for x.py check");
|
2020-05-13 17:32:43 +02:00
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-20 00:20:12 +01:00
|
|
|
Flags {
|
2017-04-01 23:48:03 +02:00
|
|
|
verbose: matches.opt_count("verbose"),
|
2019-11-10 08:41:04 +01:00
|
|
|
stage: matches.opt_str("stage").map(|j| j.parse().expect("`stage` should be a number")),
|
2018-03-27 16:06:47 +02:00
|
|
|
dry_run: matches.opt_present("dry-run"),
|
2017-04-01 23:48:03 +02:00
|
|
|
on_fail: matches.opt_str("on-fail"),
|
2018-02-24 23:56:33 +01:00
|
|
|
rustc_error_format: matches.opt_str("error-format"),
|
2020-03-31 03:21:35 +02:00
|
|
|
json_output: matches.opt_present("json-output"),
|
2019-12-22 23:42:04 +01:00
|
|
|
keep_stage: matches
|
|
|
|
.opt_strs("keep-stage")
|
|
|
|
.into_iter()
|
|
|
|
.map(|j| j.parse().expect("`keep-stage` should be a number"))
|
2018-07-14 18:58:10 +02:00
|
|
|
.collect(),
|
2020-09-23 23:25:23 +02:00
|
|
|
keep_stage_std: matches
|
|
|
|
.opt_strs("keep-stage-std")
|
|
|
|
.into_iter()
|
|
|
|
.map(|j| j.parse().expect("`keep-stage-std` should be a number"))
|
|
|
|
.collect(),
|
2020-09-06 18:57:13 +02:00
|
|
|
host: if matches.opt_present("host") {
|
|
|
|
Some(
|
|
|
|
split(&matches.opt_strs("host"))
|
|
|
|
.into_iter()
|
|
|
|
.map(|x| TargetSelection::from_user(&x))
|
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
},
|
|
|
|
target: if matches.opt_present("target") {
|
|
|
|
Some(
|
|
|
|
split(&matches.opt_strs("target"))
|
|
|
|
.into_iter()
|
|
|
|
.map(|x| TargetSelection::from_user(&x))
|
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
},
|
2015-11-20 00:20:12 +01:00
|
|
|
config: cfg_file,
|
2019-11-10 08:41:04 +01:00
|
|
|
jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")),
|
2017-08-07 07:54:09 +02:00
|
|
|
cmd,
|
2017-04-01 23:48:03 +02:00
|
|
|
incremental: matches.opt_present("incremental"),
|
2018-10-26 16:23:02 +02:00
|
|
|
exclude: split(&matches.opt_strs("exclude"))
|
2018-05-30 19:33:43 +02:00
|
|
|
.into_iter()
|
|
|
|
.map(|p| p.into())
|
|
|
|
.collect::<Vec<_>>(),
|
2020-10-09 19:51:07 +02:00
|
|
|
include_default_paths: matches.opt_present("include-default-paths"),
|
2019-07-05 13:24:58 +02:00
|
|
|
deny_warnings: parse_deny_warnings(&matches),
|
2020-01-09 22:51:38 +01:00
|
|
|
llvm_skip_rebuild: matches.opt_str("llvm-skip-rebuild").map(|s| s.to_lowercase()).map(
|
|
|
|
|s| s.parse::<bool>().expect("`llvm-skip-rebuild` should be either true or false"),
|
|
|
|
),
|
2020-11-12 22:23:35 +01:00
|
|
|
color: matches
|
|
|
|
.opt_get_default("color", Color::Auto)
|
|
|
|
.expect("`color` should be `always`, `never`, or `auto`"),
|
Utilize PGO for rustc linux dist builds
This implements support for applying PGO to the rustc compilation step (not
standard library or any tooling, including rustdoc). Expanding PGO to more tools
is not terribly difficult but will involve more work and greater CI time
commitment.
For the same reason of avoiding greater time commitment, this currently avoids
implementing for platforms outside of x86_64-unknown-linux-gnu, though in
practice it should be quite simple to extend over time to more platforms. The
initial implementation is intentionally minimal here to avoid too much work
investment before we start seeing wins for a subset of Rust users.
The choice of workloads to profile here is somewhat arbitrary, but the general
rationale was to aim for a small set that largely avoided time regressions on
perf.rust-lang.org's full suite of crates. The set chosen is libcore, cargo (and
its dependencies), and a few ad-hoc stress tests from perf.rlo. The stress tests
are arguably the most controversial, but they benefit those cases (avoiding
regressions) and do not really remove wins from other benchmarks.
The primary next step after this PR lands is to implement support for PGO in
LLVM. It is unclear whether we can afford a full LLVM rebuild in CI, though, so
the approach taken there may need to be more staggered. rustc-only PGO seems
well affordable on linux at least, giving us up to 20% wall time wins on some
crates for 15 minutes of extra CI time (1 hour up from 45 minutes).
The PGO data is uploaded to allow others to reuse it if attempting to reproduce
the CI build or potentially, in the future, on other platforms where an
off-by-one strategy is used for dist builds at minimal performance cost.
2020-12-14 19:50:59 +01:00
|
|
|
rust_profile_use: matches.opt_str("rust-profile-use"),
|
|
|
|
rust_profile_generate: matches.opt_str("rust-profile-generate"),
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-21 22:18:09 +02:00
|
|
|
impl Subcommand {
|
|
|
|
pub fn test_args(&self) -> Vec<&str> {
|
|
|
|
match *self {
|
2018-05-30 19:33:43 +02:00
|
|
|
Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
|
2019-12-22 23:42:04 +01:00
|
|
|
test_args.iter().flat_map(|s| s.split_whitespace()).collect()
|
2016-10-21 22:18:09 +02:00
|
|
|
}
|
|
|
|
_ => Vec::new(),
|
|
|
|
}
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
2017-06-02 18:27:44 +02:00
|
|
|
|
2018-01-18 23:44:41 +01:00
|
|
|
pub fn rustc_args(&self) -> Vec<&str> {
|
|
|
|
match *self {
|
2019-12-22 23:42:04 +01:00
|
|
|
Subcommand::Test { ref rustc_args, .. } => {
|
|
|
|
rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
|
|
|
|
}
|
2018-01-18 23:44:41 +01:00
|
|
|
_ => Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-27 21:37:24 +02:00
|
|
|
pub fn fail_fast(&self) -> bool {
|
2017-06-02 18:27:44 +02:00
|
|
|
match *self {
|
2017-06-27 21:37:24 +02:00
|
|
|
Subcommand::Test { fail_fast, .. } => fail_fast,
|
2017-06-02 18:27:44 +02:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2018-02-17 15:45:39 +01:00
|
|
|
|
2018-05-05 21:30:42 +02:00
|
|
|
pub fn doc_tests(&self) -> DocTests {
|
2018-02-17 15:45:39 +01:00
|
|
|
match *self {
|
|
|
|
Subcommand::Test { doc_tests, .. } => doc_tests,
|
2018-05-05 21:30:42 +02:00
|
|
|
_ => DocTests::Yes,
|
2018-02-17 15:45:39 +01:00
|
|
|
}
|
|
|
|
}
|
2018-05-16 18:17:29 +02:00
|
|
|
|
|
|
|
pub fn bless(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
Subcommand::Test { bless, .. } => bless,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2018-05-29 00:44:33 +02:00
|
|
|
|
2019-03-24 14:06:47 +01:00
|
|
|
pub fn rustfix_coverage(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
Subcommand::Test { rustfix_coverage, .. } => rustfix_coverage,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-29 00:44:33 +02:00
|
|
|
pub fn compare_mode(&self) -> Option<&str> {
|
|
|
|
match *self {
|
2019-12-22 23:42:04 +01:00
|
|
|
Subcommand::Test { ref compare_mode, .. } => compare_mode.as_ref().map(|s| &s[..]),
|
2018-05-29 00:44:33 +02:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2019-06-12 00:43:44 +02:00
|
|
|
|
|
|
|
pub fn pass(&self) -> Option<&str> {
|
|
|
|
match *self {
|
2019-12-22 23:42:04 +01:00
|
|
|
Subcommand::Test { ref pass, .. } => pass.as_ref().map(|s| &s[..]),
|
2019-06-12 00:43:44 +02:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
2020-05-22 04:48:44 +02:00
|
|
|
|
|
|
|
pub fn open(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
Subcommand::Doc { open, .. } => open,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2015-11-20 00:20:12 +01:00
|
|
|
}
|
2017-01-16 23:15:12 +01:00
|
|
|
|
2018-10-26 16:23:02 +02:00
|
|
|
fn split(s: &[String]) -> Vec<String> {
|
2020-09-30 00:50:57 +02:00
|
|
|
s.iter().flat_map(|s| s.split(',')).filter(|s| !s.is_empty()).map(|s| s.to_string()).collect()
|
2017-01-16 23:15:12 +01:00
|
|
|
}
|
2019-07-05 13:24:58 +02:00
|
|
|
|
|
|
|
fn parse_deny_warnings(matches: &getopts::Matches) -> Option<bool> {
|
2020-02-03 20:13:30 +01:00
|
|
|
match matches.opt_str("warnings").as_deref() {
|
2019-07-05 13:24:58 +02:00
|
|
|
Some("deny") => Some(true),
|
2019-09-02 20:24:40 +02:00
|
|
|
Some("warn") => Some(false),
|
2019-07-05 13:24:58 +02:00
|
|
|
Some(value) => {
|
2019-12-22 23:42:04 +01:00
|
|
|
eprintln!(r#"invalid value for --warnings: {:?}, expected "warn" or "deny""#, value,);
|
2019-07-05 13:24:58 +02:00
|
|
|
process::exit(1);
|
2019-12-22 23:42:04 +01:00
|
|
|
}
|
2019-07-05 13:24:58 +02:00
|
|
|
None => None,
|
|
|
|
}
|
|
|
|
}
|