]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #76631 - jyn514:x.py-setup, r=Mark-Simulacrum
authorRalf Jung <post@ralfj.de>
Sat, 26 Sep 2020 10:58:13 +0000 (12:58 +0200)
committerGitHub <noreply@github.com>
Sat, 26 Sep 2020 10:58:13 +0000 (12:58 +0200)
Add `x.py setup`

Closes #76503.

- Suggest `x.py setup` if config.toml doesn't exist yet
- Prompt for a profile if not given on the command line
- Print the configuration that will be used
- Print helpful starting commands after setup
- Link to the dev-guide after finishing

1  2 
src/bootstrap/CHANGELOG.md
src/bootstrap/bin/main.rs
src/bootstrap/config.rs
src/bootstrap/flags.rs

index 1510f4d59fa3474c66e31fecc6fd1c182ca3e16d,aa398f25020f1fdd56e25fd0c78272518e7bce81..dfb39c54c17235dc4556fc198606e5dd520182af
@@@ -6,6 -6,7 +6,7 @@@ The format is based on [Keep a Changelo
  
  ## [Non-breaking changes since the last major version]
  
+ - Add `x.py setup` [#76631](https://github.com/rust-lang/rust/pull/76631)
  - Add a changelog for x.py [#76626](https://github.com/rust-lang/rust/pull/76626)
  - Optionally, download LLVM from CI on Linux and NixOS
    + [#76439](https://github.com/rust-lang/rust/pull/76349)
  - Make the default stage for x.py configurable [#76625](https://github.com/rust-lang/rust/pull/76625)
  - Add a dedicated debug-logging option [#76588](https://github.com/rust-lang/rust/pull/76588)
  - Add sample defaults for x.py [#76628](https://github.com/rust-lang/rust/pull/76628)
 +- Add `--keep-stage-std`, which behaves like `keep-stage` but allows the stage
 +  0 compiler artifacts (i.e., stage1/bin/rustc) to be rebuilt if changed
 +  [#77120](https://github.com/rust-lang/rust/pull/77120).
 +
  
  ## [Version 0] - 2020-09-11
  
index 6af13fc83d0ef94131a0d6d79c09fed1583513ce,669dd7a33de187ae664270f98bc368e89c4e8f7c..637083e08d510e2f4023fe6b7b5f64b44bb6cc0d
@@@ -7,21 -7,34 +7,34 @@@
  
  use std::env;
  
- use bootstrap::{Build, Config};
+ use bootstrap::{Build, Config, Subcommand};
  
  fn main() {
      let args = env::args().skip(1).collect::<Vec<_>>();
      let config = Config::parse(&args);
  
      let changelog_suggestion = check_version(&config);
-     if let Some(suggestion) = &changelog_suggestion {
+     // NOTE: Since `./configure` generates a `config.toml`, distro maintainers will see the
+     // changelog warning, not the `x.py setup` message.
+     let suggest_setup = !config.config.exists() && !matches!(config.cmd, Subcommand::Setup { .. });
+     if suggest_setup {
+         println!("warning: you have not made a `config.toml`");
+         println!("help: consider running `x.py setup` or copying `config.toml.example`");
+     } else if let Some(suggestion) = &changelog_suggestion {
          println!("{}", suggestion);
      }
  
      Build::new(config).build();
  
-     if let Some(suggestion) = changelog_suggestion {
+     if suggest_setup {
+         println!("warning: you have not made a `config.toml`");
+         println!("help: consider running `x.py setup` or copying `config.toml.example`");
+     } else if let Some(suggestion) = &changelog_suggestion {
          println!("{}", suggestion);
+     }
+     if suggest_setup || changelog_suggestion.is_some() {
          println!("note: this message was printed twice to make it more likely to be seen");
      }
  }
@@@ -40,7 -53,7 +53,7 @@@ fn check_version(config: &Config) -> Op
          }
      } else {
          msg.push_str("warning: x.py has made several changes recently you may want to look at\n");
 -        format!("add `changelog-seen = {}` to `config.toml`", VERSION)
 +        format!("add `changelog-seen = {}` at the top of `config.toml`", VERSION)
      };
  
      msg.push_str("help: consider looking at the changes in `src/bootstrap/CHANGELOG.md`\n");
diff --combined src/bootstrap/config.rs
index 53fef7a838df62dc11152491dea44a32ac0d1719,46a9d989652e93af5405d6728df9d1baafd8b0a0..b14746dabb93a83eff5cdf9caea130b602668bd9
@@@ -71,8 -71,9 +71,10 @@@ pub struct Config 
      pub on_fail: Option<String>,
      pub stage: u32,
      pub keep_stage: Vec<u32>,
 +    pub keep_stage_std: Vec<u32>,
      pub src: PathBuf,
+     // defaults to `config.toml`
+     pub config: PathBuf,
      pub jobs: Option<u32>,
      pub cmd: Subcommand,
      pub incremental: bool,
@@@ -513,6 -514,7 +515,7 @@@ impl Config 
          config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
          config.deny_warnings = true;
          config.missing_tools = false;
+         config.config = PathBuf::from("config.toml");
  
          // set by bootstrap.py
          config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
          config.incremental = flags.incremental;
          config.dry_run = flags.dry_run;
          config.keep_stage = flags.keep_stage;
 +        config.keep_stage_std = flags.keep_stage_std;
          config.bindir = "bin".into(); // default
          if let Some(value) = flags.deny_warnings {
              config.deny_warnings = value;
          let get_toml = |file: PathBuf| {
              use std::process;
  
-             let contents = t!(fs::read_to_string(&file), "configuration file did not exist");
+             let contents = t!(fs::read_to_string(&file), "`include` config not found");
              match toml::from_str(&contents) {
                  Ok(table) => table,
                  Err(err) => {
              | Subcommand::Clippy { .. }
              | Subcommand::Fix { .. }
              | Subcommand::Run { .. }
+             | Subcommand::Setup { .. }
              | Subcommand::Format { .. } => flags.stage.unwrap_or(0),
          };
  
                  | Subcommand::Clippy { .. }
                  | Subcommand::Fix { .. }
                  | Subcommand::Run { .. }
+                 | Subcommand::Setup { .. }
                  | Subcommand::Format { .. } => {}
              }
          }
diff --combined src/bootstrap/flags.rs
index dad31fc77be17677c8e1e61b9ca1aeea96fe6c1a,643edeb8321bae12aab17f6b7e65e12b8e5b6ee7..a12fc50afad587cc10be1d2e58c1bf065e8d5c98
@@@ -7,6 -7,7 +7,7 @@@ use std::env
  use std::path::PathBuf;
  use std::process;
  
+ use build_helper::t;
  use getopts::Options;
  
  use crate::builder::Builder;
@@@ -19,7 -20,6 +20,7 @@@ pub struct Flags 
      pub on_fail: Option<String>,
      pub stage: Option<u32>,
      pub keep_stage: Vec<u32>,
 +    pub keep_stage_std: Vec<u32>,
  
      pub host: Option<Vec<TargetSelection>>,
      pub target: Option<Vec<TargetSelection>>,
@@@ -89,6 -89,9 +90,9 @@@ pub enum Subcommand 
      Run {
          paths: Vec<PathBuf>,
      },
+     Setup {
+         path: String,
+     },
  }
  
  impl Default for Subcommand {
@@@ -145,13 -148,6 +149,13 @@@ To learn more about a subcommand, run `
              (pass multiple times to keep e.g., both stages 0 and 1)",
              "N",
          );
 +        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",
 +        );
          opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
          let j_msg = format!(
              "number of jobs to run in parallel; \
                  || (s == "install")
                  || (s == "run")
                  || (s == "r")
+                 || (s == "setup")
          });
          let subcommand = match subcommand {
              Some(s) => s,
@@@ -453,10 -450,21 +458,21 @@@ Arguments
      At least a tool needs to be called.",
                  );
              }
+             "setup" => {
+                 subcommand_help.push_str(
+                     "\n
+ 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.",
+                 );
+             }
              _ => {}
          };
          // Get any optional paths which occur after the subcommand
-         let paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
+         let mut paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
  
          let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);
          let verbose = matches.opt_present("verbose");
                  }
                  Subcommand::Run { paths }
              }
+             "setup" => {
+                 let path = if paths.len() > 1 {
+                     println!("\nat most one profile can be passed to setup\n");
+                     usage(1, &opts, verbose, &subcommand_help)
+                 } else if let Some(path) = paths.pop() {
+                     t!(path.into_os_string().into_string().map_err(|path| format!(
+                         "{} is not a valid UTF8 string",
+                         path.to_string_lossy()
+                     )))
+                 } else {
+                     t!(crate::setup::interactive_path())
+                 };
+                 Subcommand::Setup { path }
+             }
              _ => {
                  usage(1, &opts, verbose, &subcommand_help);
              }
                  println!("--stage not supported for x.py check, always treated as stage 0");
                  process::exit(1);
              }
 -            if matches.opt_str("keep-stage").is_some() {
 +            if matches.opt_str("keep-stage").is_some()
 +                || matches.opt_str("keep-stage-std").is_some()
 +            {
                  println!("--keep-stage not supported for x.py check, only one stage available");
                  process::exit(1);
              }
                  .into_iter()
                  .map(|j| j.parse().expect("`keep-stage` should be a number"))
                  .collect(),
 +            keep_stage_std: matches
 +                .opt_strs("keep-stage-std")
 +                .into_iter()
 +                .map(|j| j.parse().expect("`keep-stage-std` should be a number"))
 +                .collect(),
              host: if matches.opt_present("host") {
                  Some(
                      split(&matches.opt_strs("host"))