]> git.lizzy.rs Git - rust.git/blobdiff - src/bootstrap/lib.rs
Auto merge of #67940 - JohnTitor:rustc-guide, r=JohnTitor
[rust.git] / src / bootstrap / lib.rs
index 080bef6853a20ce39fdd22ff0011f6918188bd34..1fee3fd9ac1d26038726a25287061fd75e7ade5e 100644 (file)
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 
-use std::cell::{RefCell, Cell};
-use std::collections::{HashSet, HashMap};
+use std::cell::{Cell, RefCell};
+use std::collections::{HashMap, HashSet};
 use std::env;
-use std::fs::{self, OpenOptions, File};
-use std::io::{Seek, SeekFrom, Write, Read};
-use std::path::{PathBuf, Path};
+use std::fs::{self, File, OpenOptions};
+use std::io::{Read, Seek, SeekFrom, Write};
+use std::path::{Path, PathBuf};
 use std::process::{self, Command};
 use std::slice;
 use std::str;
 #[cfg(windows)]
 use std::os::windows::fs::symlink_file;
 
-use build_helper::{
-    mtime, output, run, run_suppressed, t, try_run, try_run_suppressed,
-};
+use build_helper::{mtime, output, run, run_suppressed, t, try_run, try_run_suppressed};
 use filetime::FileTime;
 
 use crate::util::{exe, libdir, CiEnv};
 
+mod builder;
+mod cache;
 mod cc_detect;
 mod channel;
 mod check;
-mod test;
 mod clean;
 mod compile;
-mod metadata;
 mod config;
 mod dist;
 mod doc;
 mod flags;
+mod format;
 mod install;
+mod metadata;
 mod native;
 mod sanity;
-pub mod util;
-mod builder;
-mod cache;
+mod test;
 mod tool;
 mod toolstate;
+pub mod util;
 
 #[cfg(windows)]
 mod job;
@@ -162,13 +161,12 @@ pub unsafe fn setup(build: &mut crate::Build) {
 
 #[cfg(any(target_os = "haiku", target_os = "hermit", not(any(unix, windows))))]
 mod job {
-    pub unsafe fn setup(_build: &mut crate::Build) {
-    }
+    pub unsafe fn setup(_build: &mut crate::Build) {}
 }
 
+use crate::cache::{Interned, INTERNER};
 pub use crate::config::Config;
 use crate::flags::Subcommand;
-use crate::cache::{Interned, INTERNER};
 
 const LLVM_TOOLS: &[&str] = &[
     "llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
@@ -178,7 +176,7 @@ pub unsafe fn setup(_build: &mut crate::Build) {
     "llvm-readobj", // used to get information from ELFs/objects that the other tools don't provide
     "llvm-size", // used to prints the size of the linker sections of a program
     "llvm-strip", // used to discard symbols from binary files to reduce their size
-    "llvm-ar" // used for creating and modifying archive files
+    "llvm-ar", // used for creating and modifying archive files
 ];
 
 /// A structure representing a Rust compiler.
@@ -257,10 +255,8 @@ pub struct Build {
     ci_env: CiEnv,
     delayed_failures: RefCell<Vec<String>>,
     prerelease_version: Cell<Option<u32>>,
-    tool_artifacts: RefCell<HashMap<
-        Interned<String>,
-        HashMap<String, (&'static str, PathBuf, Vec<String>)>
-    >>,
+    tool_artifacts:
+        RefCell<HashMap<Interned<String>, HashMap<String, (&'static str, PathBuf, Vec<String>)>>>,
 }
 
 #[derive(Debug)]
@@ -273,8 +269,7 @@ struct Crate {
 
 impl Crate {
     fn is_local(&self, build: &Build) -> bool {
-        self.path.starts_with(&build.config.src) &&
-        !self.path.to_string_lossy().ends_with("_shim")
+        self.path.starts_with(&build.config.src) && !self.path.to_string_lossy().ends_with("_shim")
     }
 
     fn local_path(&self, build: &Build) -> PathBuf {
@@ -315,7 +310,7 @@ impl Mode {
     pub fn is_tool(&self) -> bool {
         match self {
             Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => true,
-            _ => false
+            _ => false,
         }
     }
 }
@@ -330,12 +325,10 @@ pub fn new(config: Config) -> Build {
         let out = config.out.clone();
 
         let is_sudo = match env::var_os("SUDO_USER") {
-            Some(sudo_user) => {
-                match env::var_os("USER") {
-                    Some(user) => user != sudo_user,
-                    None => false,
-                }
-            }
+            Some(sudo_user) => match env::var_os("USER") {
+                Some(user) => user != sudo_user,
+                None => false,
+            },
             None => false,
         };
 
@@ -392,11 +385,15 @@ pub fn new(config: Config) -> Build {
 
         // If local-rust is the same major.minor as the current version, then force a
         // local-rebuild
-        let local_version_verbose = output(
-            Command::new(&build.initial_rustc).arg("--version").arg("--verbose"));
+        let local_version_verbose =
+            output(Command::new(&build.initial_rustc).arg("--version").arg("--verbose"));
         let local_release = local_version_verbose
-            .lines().filter(|x| x.starts_with("release:"))
-            .next().unwrap().trim_start_matches("release:").trim();
+            .lines()
+            .filter(|x| x.starts_with("release:"))
+            .next()
+            .unwrap()
+            .trim_start_matches("release:")
+            .trim();
         let my_version = channel::CFG_RELEASE_NUM;
         if local_release.split('.').take(2).eq(my_version.split('.').take(2)) {
             build.verbose(&format!("auto-detected local-rebuild {}", local_release));
@@ -410,9 +407,7 @@ pub fn new(config: Config) -> Build {
     }
 
     pub fn build_triple(&self) -> &[Interned<String>] {
-        unsafe {
-            slice::from_raw_parts(&self.build, 1)
-        }
+        unsafe { slice::from_raw_parts(&self.build, 1) }
     }
 
     /// Executes the entire build, as configured by the flags and configuration.
@@ -421,6 +416,10 @@ pub fn build(&mut self) {
             job::setup(self);
         }
 
+        if let Subcommand::Format { check } = self.config.cmd {
+            return format::format(self, check);
+        }
+
         if let Subcommand::Clean { all } = self.config.cmd {
             return clean::clean(self, all);
         }
@@ -509,7 +508,7 @@ fn rustc_features(&self) -> String {
     /// Component directory that Cargo will produce output into (e.g.
     /// release/debug)
     fn cargo_dir(&self) -> &'static str {
-        if self.config.rust_optimize {"release"} else {"debug"}
+        if self.config.rust_optimize { "release" } else { "debug" }
     }
 
     fn tools_dir(&self, compiler: Compiler) -> PathBuf {
@@ -530,17 +529,13 @@ fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf {
             Mode::ToolBootstrap => "-bootstrap-tools",
             Mode::ToolStd | Mode::ToolRustc => "-tools",
         };
-        self.out.join(&*compiler.host)
-                .join(format!("stage{}{}", compiler.stage, suffix))
+        self.out.join(&*compiler.host).join(format!("stage{}{}", compiler.stage, suffix))
     }
 
     /// Returns the root output directory for all Cargo output in a given stage,
     /// running a particular compiler, whether or not we're building the
     /// standard library, and targeting the specified architecture.
-    fn cargo_out(&self,
-                 compiler: Compiler,
-                 mode: Mode,
-                 target: Interned<String>) -> PathBuf {
+    fn cargo_out(&self, compiler: Compiler, mode: Mode, target: Interned<String>) -> PathBuf {
         self.stage_out(compiler, mode).join(&*target).join(self.cargo_dir())
     }
 
@@ -584,7 +579,7 @@ fn crate_doc_out(&self, target: Interned<String>) -> PathBuf {
     fn is_rust_llvm(&self, target: Interned<String>) -> bool {
         match self.config.target_config.get(&target) {
             Some(ref c) => c.llvm_config.is_none(),
-            None => true
+            None => true,
         }
     }
 
@@ -602,8 +597,8 @@ fn llvm_filecheck(&self, target: Interned<String>) -> PathBuf {
                 // On Fedora the system LLVM installs FileCheck in the
                 // llvm subdirectory of the libdir.
                 let llvm_libdir = output(Command::new(s).arg("--libdir"));
-                let lib_filecheck = Path::new(llvm_libdir.trim())
-                    .join("llvm").join(exe("FileCheck", &*target));
+                let lib_filecheck =
+                    Path::new(llvm_libdir.trim()).join("llvm").join(exe("FileCheck", &*target));
                 if lib_filecheck.exists() {
                     lib_filecheck
                 } else {
@@ -662,14 +657,18 @@ fn rustc_snapshot_sysroot(&self) -> &Path {
 
     /// Runs a command, printing out nice contextual information if it fails.
     fn run(&self, cmd: &mut Command) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         self.verbose(&format!("running: {:?}", cmd));
         run(cmd)
     }
 
     /// Runs a command, printing out nice contextual information if it fails.
     fn run_quiet(&self, cmd: &mut Command) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         self.verbose(&format!("running: {:?}", cmd));
         run_suppressed(cmd)
     }
@@ -678,7 +677,9 @@ fn run_quiet(&self, cmd: &mut Command) {
     /// Exits if the command failed to execute at all, otherwise returns its
     /// `status.success()`.
     fn try_run(&self, cmd: &mut Command) -> bool {
-        if self.config.dry_run { return true; }
+        if self.config.dry_run {
+            return true;
+        }
         self.verbose(&format!("running: {:?}", cmd));
         try_run(cmd)
     }
@@ -687,7 +688,9 @@ fn try_run(&self, cmd: &mut Command) -> bool {
     /// Exits if the command failed to execute at all, otherwise returns its
     /// `status.success()`.
     fn try_run_quiet(&self, cmd: &mut Command) -> bool {
-        if self.config.dry_run { return true; }
+        if self.config.dry_run {
+            return true;
+        }
         self.verbose(&format!("running: {:?}", cmd));
         try_run_suppressed(cmd)
     }
@@ -715,7 +718,9 @@ fn verbose_than(&self, level: usize, msg: &str) {
     }
 
     fn info(&self, msg: &str) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         println!("{}", msg);
     }
 
@@ -727,7 +732,7 @@ fn jobs(&self) -> u32 {
 
     fn debuginfo_map(&self, which: GitRepo) -> Option<String> {
         if !self.config.rust_remap_debuginfo {
-            return None
+            return None;
         }
 
         let path = match which {
@@ -750,10 +755,12 @@ fn cc(&self, target: Interned<String>) -> &Path {
     fn cflags(&self, target: Interned<String>, which: GitRepo) -> Vec<String> {
         // Filter out -O and /O (the optimization flags) that we picked up from
         // cc-rs because the build scripts will determine that for themselves.
-        let mut base = self.cc[&target].args().iter()
-                           .map(|s| s.to_string_lossy().into_owned())
-                           .filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
-                           .collect::<Vec<String>>();
+        let mut base = self.cc[&target]
+            .args()
+            .iter()
+            .map(|s| s.to_string_lossy().into_owned())
+            .filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
+            .collect::<Vec<String>>();
 
         // If we're compiling on macOS then we add a few unconditional flags
         // indicating that we want libc++ (more filled out than libstdc++) and
@@ -771,7 +778,7 @@ fn cflags(&self, target: Interned<String>, which: GitRepo) -> Vec<String> {
         }
 
         if let Some(map) = self.debuginfo_map(which) {
-        let cc = self.cc(target);
+            let cc = self.cc(target);
             if cc.ends_with("clang") || cc.ends_with("gcc") {
                 base.push(format!("-fdebug-prefix-map={}", map));
             } else if cc.ends_with("clang-cl.exe") {
@@ -796,20 +803,21 @@ fn ranlib(&self, target: Interned<String>) -> Option<&Path> {
     fn cxx(&self, target: Interned<String>) -> Result<&Path, String> {
         match self.cxx.get(&target) {
             Some(p) => Ok(p.path()),
-            None => Err(format!(
-                    "target `{}` is not configured as a host, only as a target",
-                    target))
+            None => {
+                Err(format!("target `{}` is not configured as a host, only as a target", target))
+            }
         }
     }
 
     /// Returns the path to the linker for the given target if it needs to be overridden.
     fn linker(&self, target: Interned<String>) -> Option<&Path> {
-        if let Some(linker) = self.config.target_config.get(&target)
-                                                       .and_then(|c| c.linker.as_ref()) {
+        if let Some(linker) = self.config.target_config.get(&target).and_then(|c| c.linker.as_ref())
+        {
             Some(linker)
-        } else if target != self.config.build &&
-                  util::use_host_linker(&target) &&
-                  !target.contains("msvc") {
+        } else if target != self.config.build
+            && util::use_host_linker(&target)
+            && !target.contains("msvc")
+        {
             Some(self.cc(target))
         } else {
             None
@@ -821,14 +829,15 @@ fn crt_static(&self, target: Interned<String>) -> Option<bool> {
         if target.contains("pc-windows-msvc") {
             Some(true)
         } else {
-            self.config.target_config.get(&target)
-                .and_then(|t| t.crt_static)
+            self.config.target_config.get(&target).and_then(|t| t.crt_static)
         }
     }
 
     /// Returns the "musl root" for this `target`, if defined
     fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
-        self.config.target_config.get(&target)
+        self.config
+            .target_config
+            .get(&target)
             .and_then(|t| t.musl_root.as_ref())
             .or(self.config.musl_root.as_ref())
             .map(|p| &**p)
@@ -836,22 +845,20 @@ fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
 
     /// Returns the sysroot for the wasi target, if defined
     fn wasi_root(&self, target: Interned<String>) -> Option<&Path> {
-        self.config.target_config.get(&target)
-            .and_then(|t| t.wasi_root.as_ref())
-            .map(|p| &**p)
+        self.config.target_config.get(&target).and_then(|t| t.wasi_root.as_ref()).map(|p| &**p)
     }
 
     /// Returns `true` if this is a no-std `target`, if defined
     fn no_std(&self, target: Interned<String>) -> Option<bool> {
-        self.config.target_config.get(&target)
-            .map(|t| t.no_std)
+        self.config.target_config.get(&target).map(|t| t.no_std)
     }
 
     /// Returns `true` if the target will be tested using the `remote-test-client`
     /// and `remote-test-server` binaries.
     fn remote_tested(&self, target: Interned<String>) -> bool {
-        self.qemu_rootfs(target).is_some() || target.contains("android") ||
-        env::var_os("TEST_DEVICE_ADDR").is_some()
+        self.qemu_rootfs(target).is_some()
+            || target.contains("android")
+            || env::var_os("TEST_DEVICE_ADDR").is_some()
     }
 
     /// Returns the root of the "rootfs" image that this target will be using,
@@ -860,9 +867,7 @@ fn remote_tested(&self, target: Interned<String>) -> bool {
     /// If `Some` is returned then that means that tests for this target are
     /// emulated with QEMU and binaries will need to be shipped to the emulator.
     fn qemu_rootfs(&self, target: Interned<String>) -> Option<&Path> {
-        self.config.target_config.get(&target)
-            .and_then(|t| t.qemu_rootfs.as_ref())
-            .map(|p| &**p)
+        self.config.target_config.get(&target).and_then(|t| t.qemu_rootfs.as_ref()).map(|p| &**p)
     }
 
     /// Path to the python interpreter to use
@@ -894,9 +899,9 @@ fn extended_error_dir(&self) -> PathBuf {
     /// When all of these conditions are met the build will lift artifacts from
     /// the previous stage forward.
     fn force_use_stage1(&self, compiler: Compiler, target: Interned<String>) -> bool {
-        !self.config.full_bootstrap &&
-            compiler.stage >= 2 &&
-            (self.hosts.iter().any(|h| *h == target) || target == self.build)
+        !self.config.full_bootstrap
+            && compiler.stage >= 2
+            && (self.hosts.iter().any(|h| *h == target) || target == self.build)
     }
 
     /// Given `num` in the form "a.b.c" return a "release string" which
@@ -907,11 +912,13 @@ fn force_use_stage1(&self, compiler: Compiler, target: Interned<String>) -> bool
     fn release(&self, num: &str) -> String {
         match &self.config.channel[..] {
             "stable" => num.to_string(),
-            "beta" => if self.rust_info.is_git() {
-                format!("{}-beta.{}", num, self.beta_prerelease_version())
-            } else {
-                format!("{}-beta", num)
-            },
+            "beta" => {
+                if self.rust_info.is_git() {
+                    format!("{}-beta.{}", num, self.beta_prerelease_version())
+                } else {
+                    format!("{}-beta", num)
+                }
+            }
             "nightly" => format!("{}-nightly", num),
             _ => format!("{}-dev", num),
         }
@@ -919,33 +926,21 @@ fn release(&self, num: &str) -> String {
 
     fn beta_prerelease_version(&self) -> u32 {
         if let Some(s) = self.prerelease_version.get() {
-            return s
+            return s;
         }
 
         let beta = output(
-            Command::new("git")
-                .arg("ls-remote")
-                .arg("origin")
-                .arg("beta")
-                .current_dir(&self.src)
+            Command::new("git").arg("ls-remote").arg("origin").arg("beta").current_dir(&self.src),
         );
         let beta = beta.trim().split_whitespace().next().unwrap();
         let master = output(
-            Command::new("git")
-                .arg("ls-remote")
-                .arg("origin")
-                .arg("master")
-                .current_dir(&self.src)
+            Command::new("git").arg("ls-remote").arg("origin").arg("master").current_dir(&self.src),
         );
         let master = master.trim().split_whitespace().next().unwrap();
 
         // Figure out where the current beta branch started.
         let base = output(
-            Command::new("git")
-                .arg("merge-base")
-                .arg(beta)
-                .arg(master)
-                .current_dir(&self.src),
+            Command::new("git").arg("merge-base").arg(beta).arg(master).current_dir(&self.src),
         );
         let base = base.trim();
 
@@ -1056,7 +1051,7 @@ fn release_num(&self, package: &str) -> String {
             let prefix = "version = \"";
             let suffix = "\"";
             if line.starts_with(prefix) && line.ends_with(suffix) {
-                return line[prefix.len()..line.len() - suffix.len()].to_string()
+                return line[prefix.len()..line.len() - suffix.len()].to_string();
             }
         }
 
@@ -1101,7 +1096,7 @@ fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> {
         // run_cargo for more information (in compile.rs).
         for part in contents.split(|b| *b == 0) {
             if part.is_empty() {
-                continue
+                continue;
             }
             let host = part[0] as char == 'h';
             let path = PathBuf::from(t!(str::from_utf8(&part[1..])));
@@ -1112,9 +1107,13 @@ fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> {
 
     /// Copies a file from `src` to `dst`
     pub fn copy(&self, src: &Path, dst: &Path) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst));
-        if src == dst { return; }
+        if src == dst {
+            return;
+        }
         let _ = fs::remove_file(&dst);
         let metadata = t!(src.symlink_metadata());
         if metadata.file_type().is_symlink() {
@@ -1126,8 +1125,7 @@ pub fn copy(&self, src: &Path, dst: &Path) {
             // just fall back to a slow `copy` operation.
         } else {
             if let Err(e) = fs::copy(src, dst) {
-                panic!("failed to copy `{}` to `{}`: {}", src.display(),
-                       dst.display(), e)
+                panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
             }
             t!(fs::set_permissions(dst, metadata.permissions()));
             let atime = FileTime::from_last_access_time(&metadata);
@@ -1139,7 +1137,9 @@ pub fn copy(&self, src: &Path, dst: &Path) {
     /// Search-and-replaces within a file. (Not maximally efficiently: allocates a
     /// new string for each replacement.)
     pub fn replace_in_file(&self, path: &Path, replacements: &[(&str, &str)]) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         let mut contents = String::new();
         let mut file = t!(OpenOptions::new().read(true).write(true).open(path));
         t!(file.read_to_string(&mut contents));
@@ -1154,7 +1154,9 @@ pub fn replace_in_file(&self, path: &Path, replacements: &[(&str, &str)]) {
     /// Copies the `src` directory recursively to `dst`. Both are assumed to exist
     /// when this function is called.
     pub fn cp_r(&self, src: &Path, dst: &Path) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         for f in self.read_dir(src) {
             let path = f.path();
             let name = path.file_name().unwrap();
@@ -1205,7 +1207,9 @@ fn copy_to_folder(&self, src: &Path, dest_folder: &Path) {
     }
 
     fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         let dst = dstdir.join(src.file_name().unwrap());
         self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst));
         t!(fs::create_dir_all(dstdir));
@@ -1216,8 +1220,7 @@ fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
             }
             let metadata = t!(src.symlink_metadata());
             if let Err(e) = fs::copy(&src, &dst) {
-                panic!("failed to copy `{}` to `{}`: {}", src.display(),
-                       dst.display(), e)
+                panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
             }
             t!(fs::set_permissions(&dst, metadata.permissions()));
             let atime = FileTime::from_last_access_time(&metadata);
@@ -1228,26 +1231,34 @@ fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
     }
 
     fn create(&self, path: &Path, s: &str) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         t!(fs::write(path, s));
     }
 
     fn read(&self, path: &Path) -> String {
-        if self.config.dry_run { return String::new(); }
+        if self.config.dry_run {
+            return String::new();
+        }
         t!(fs::read_to_string(path))
     }
 
     fn create_dir(&self, dir: &Path) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         t!(fs::create_dir_all(dir))
     }
 
     fn remove_dir(&self, dir: &Path) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         t!(fs::remove_dir_all(dir))
     }
 
-    fn read_dir(&self, dir: &Path) -> impl Iterator<Item=fs::DirEntry> {
+    fn read_dir(&self, dir: &Path) -> impl Iterator<Item = fs::DirEntry> {
         let iter = match fs::read_dir(dir) {
             Ok(v) => v,
             Err(_) if self.config.dry_run => return vec![].into_iter(),
@@ -1257,7 +1268,9 @@ fn read_dir(&self, dir: &Path) -> impl Iterator<Item=fs::DirEntry> {
     }
 
     fn remove(&self, f: &Path) {
-        if self.config.dry_run { return; }
+        if self.config.dry_run {
+            return;
+        }
         fs::remove_file(f).unwrap_or_else(|_| panic!("failed to remove {:?}", f));
     }
 }
@@ -1270,7 +1283,6 @@ fn chmod(path: &Path, perms: u32) {
 #[cfg(windows)]
 fn chmod(_path: &Path, _perms: u32) {}
 
-
 impl Compiler {
     pub fn with_stage(mut self, stage: u32) -> Compiler {
         self.stage = stage;