未验证 提交 ab7a356b 编写于 作者: M Matthias Krüger 提交者: GitHub

Rollup merge of #92297 - bjorn3:smaller_bootstrap, r=Mark-Simulacrum

Reduce compile time of rustbuild

Best reviewed commit by commit. The `ignore` crate and it's dependencies are probably responsible for the majority of the compile time after this PR.

cc `@jyn514` as you got a couple of open rustbuild PR.
......@@ -175,9 +175,7 @@ dependencies = [
"filetime",
"getopts",
"ignore",
"lazy_static",
"libc",
"merge",
"num_cpus",
"once_cell",
"opener",
......@@ -2221,28 +2219,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "merge"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9"
dependencies = [
"merge_derive",
"num-traits",
]
[[package]]
name = "merge_derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "minifier"
version = "0.0.41"
......
......@@ -44,11 +44,9 @@ libc = "0.2"
serde = { version = "1.0.8", features = ["derive"] }
serde_json = "1.0.2"
toml = "0.5"
lazy_static = "1.3.0"
time = "0.1"
ignore = "0.4.10"
opener = "0.5"
merge = "0.1.0"
once_cell = "1.7.2"
[target.'cfg(windows)'.dependencies.winapi]
......
......@@ -15,6 +15,8 @@
//! switching compilers for the bootstrap and for build scripts will probably
//! never get replaced.
include!("../dylib_util.rs");
use std::env;
use std::path::PathBuf;
use std::process::{Child, Command};
......@@ -50,11 +52,11 @@ fn main() {
let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc));
let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir));
let mut dylib_path = bootstrap::util::dylib_path();
let mut dylib_path = dylib_path();
dylib_path.insert(0, PathBuf::from(&libdir));
let mut cmd = Command::new(rustc);
cmd.args(&args).env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap());
cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
// Get the name of the crate we're compiling, if any.
let crate_name =
......@@ -161,7 +163,7 @@ fn main() {
eprintln!(
"{} command: {:?}={:?} {:?}",
prefix,
bootstrap::util::dylib_path_var(),
dylib_path_var(),
env::join_paths(&dylib_path).unwrap(),
cmd,
);
......
......@@ -7,6 +7,8 @@
use std::path::PathBuf;
use std::process::Command;
include!("../dylib_util.rs");
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
......@@ -20,14 +22,14 @@ fn main() {
Err(_) => 0,
};
let mut dylib_path = bootstrap::util::dylib_path();
let mut dylib_path = dylib_path();
dylib_path.insert(0, PathBuf::from(libdir.clone()));
let mut cmd = Command::new(rustdoc);
cmd.args(&args)
.arg("--sysroot")
.arg(&sysroot)
.env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap());
.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
// Force all crates compiled by this compiler to (a) be unstable and (b)
// allow the `rustc_private` feature to link to other unstable crates
......@@ -59,7 +61,7 @@ fn main() {
if verbose > 1 {
eprintln!(
"rustdoc command: {:?}={:?} {:?}",
bootstrap::util::dylib_path_var(),
dylib_path_var(),
env::join_paths(&dylib_path).unwrap(),
cmd,
);
......
......@@ -351,7 +351,6 @@ pub enum Kind {
Check,
Clippy,
Fix,
Format,
Test,
Bench,
Dist,
......@@ -399,7 +398,7 @@ fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> {
native::Lld,
native::CrtBeginEnd
),
Kind::Check | Kind::Clippy { .. } | Kind::Fix | Kind::Format => describe!(
Kind::Check | Kind::Clippy { .. } | Kind::Fix => describe!(
check::Std,
check::Rustc,
check::Rustdoc,
......
......@@ -13,7 +13,8 @@
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use lazy_static::lazy_static;
// FIXME: replace with std::lazy after it gets stabilized and reaches beta
use once_cell::sync::Lazy;
use crate::builder::Step;
......@@ -222,9 +223,7 @@ pub fn intern_path(&self, s: PathBuf) -> Interned<PathBuf> {
}
}
lazy_static! {
pub static ref INTERNER: Interner = Interner::default();
}
pub static INTERNER: Lazy<Interner> = Lazy::new(Interner::default);
/// This is essentially a `HashMap` which allows storing any type in its input and
/// any type in its output. It is a write-once cache; values are never evicted,
......
......@@ -18,7 +18,6 @@
use crate::flags::{Color, Flags};
use crate::util::exe;
use build_helper::t;
use merge::Merge;
use serde::Deserialize;
macro_rules! check_ci_llvm {
......@@ -334,6 +333,10 @@ struct TomlConfig {
profile: Option<String>,
}
trait Merge {
fn merge(&mut self, other: Self);
}
impl Merge for TomlConfig {
fn merge(
&mut self,
......@@ -357,105 +360,136 @@ fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>) {
}
}
/// TOML representation of various global build decisions.
#[derive(Deserialize, Default, Clone, Merge)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Build {
build: Option<String>,
host: Option<Vec<String>>,
target: Option<Vec<String>>,
// This is ignored, the rust code always gets the build directory from the `BUILD_DIR` env variable
build_dir: Option<String>,
cargo: Option<String>,
rustc: Option<String>,
rustfmt: Option<PathBuf>,
docs: Option<bool>,
compiler_docs: Option<bool>,
docs_minification: Option<bool>,
submodules: Option<bool>,
fast_submodules: Option<bool>,
gdb: Option<String>,
nodejs: Option<String>,
npm: Option<String>,
python: Option<String>,
locked_deps: Option<bool>,
vendor: Option<bool>,
full_bootstrap: Option<bool>,
extended: Option<bool>,
tools: Option<HashSet<String>>,
verbose: Option<usize>,
sanitizers: Option<bool>,
profiler: Option<bool>,
cargo_native_static: Option<bool>,
low_priority: Option<bool>,
configure_args: Option<Vec<String>>,
local_rebuild: Option<bool>,
print_step_timings: Option<bool>,
print_step_rusage: Option<bool>,
check_stage: Option<u32>,
doc_stage: Option<u32>,
build_stage: Option<u32>,
test_stage: Option<u32>,
install_stage: Option<u32>,
dist_stage: Option<u32>,
bench_stage: Option<u32>,
patch_binaries_for_nix: Option<bool>,
// We are using a decl macro instead of a derive proc macro here to reduce the compile time of
// rustbuild.
macro_rules! derive_merge {
($(#[$attr:meta])* struct $name:ident {
$($field:ident: $field_ty:ty,)*
}) => {
$(#[$attr])*
struct $name {
$($field: $field_ty,)*
}
impl Merge for $name {
fn merge(&mut self, other: Self) {
$(
if !self.$field.is_some() {
self.$field = other.$field;
}
)*
}
}
}
}
/// TOML representation of various global install decisions.
#[derive(Deserialize, Default, Clone, Merge)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Install {
prefix: Option<String>,
sysconfdir: Option<String>,
docdir: Option<String>,
bindir: Option<String>,
libdir: Option<String>,
mandir: Option<String>,
datadir: Option<String>,
derive_merge! {
/// TOML representation of various global build decisions.
#[derive(Deserialize, Default, Clone)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Build {
build: Option<String>,
host: Option<Vec<String>>,
target: Option<Vec<String>>,
// This is ignored, the rust code always gets the build directory from the `BUILD_DIR` env variable
build_dir: Option<String>,
cargo: Option<String>,
rustc: Option<String>,
rustfmt: Option<PathBuf>,
docs: Option<bool>,
compiler_docs: Option<bool>,
docs_minification: Option<bool>,
submodules: Option<bool>,
fast_submodules: Option<bool>,
gdb: Option<String>,
nodejs: Option<String>,
npm: Option<String>,
python: Option<String>,
locked_deps: Option<bool>,
vendor: Option<bool>,
full_bootstrap: Option<bool>,
extended: Option<bool>,
tools: Option<HashSet<String>>,
verbose: Option<usize>,
sanitizers: Option<bool>,
profiler: Option<bool>,
cargo_native_static: Option<bool>,
low_priority: Option<bool>,
configure_args: Option<Vec<String>>,
local_rebuild: Option<bool>,
print_step_timings: Option<bool>,
print_step_rusage: Option<bool>,
check_stage: Option<u32>,
doc_stage: Option<u32>,
build_stage: Option<u32>,
test_stage: Option<u32>,
install_stage: Option<u32>,
dist_stage: Option<u32>,
bench_stage: Option<u32>,
patch_binaries_for_nix: Option<bool>,
}
}
/// TOML representation of how the LLVM build is configured.
#[derive(Deserialize, Default, Merge)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Llvm {
skip_rebuild: Option<bool>,
optimize: Option<bool>,
thin_lto: Option<bool>,
release_debuginfo: Option<bool>,
assertions: Option<bool>,
tests: Option<bool>,
plugins: Option<bool>,
ccache: Option<StringOrBool>,
version_check: Option<bool>,
static_libstdcpp: Option<bool>,
ninja: Option<bool>,
targets: Option<String>,
experimental_targets: Option<String>,
link_jobs: Option<u32>,
link_shared: Option<bool>,
version_suffix: Option<String>,
clang_cl: Option<String>,
cflags: Option<String>,
cxxflags: Option<String>,
ldflags: Option<String>,
use_libcxx: Option<bool>,
use_linker: Option<String>,
allow_old_toolchain: Option<bool>,
polly: Option<bool>,
clang: Option<bool>,
download_ci_llvm: Option<StringOrBool>,
derive_merge! {
/// TOML representation of various global install decisions.
#[derive(Deserialize, Default, Clone)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Install {
prefix: Option<String>,
sysconfdir: Option<String>,
docdir: Option<String>,
bindir: Option<String>,
libdir: Option<String>,
mandir: Option<String>,
datadir: Option<String>,
}
}
#[derive(Deserialize, Default, Clone, Merge)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Dist {
sign_folder: Option<String>,
gpg_password_file: Option<String>,
upload_addr: Option<String>,
src_tarball: Option<bool>,
missing_tools: Option<bool>,
compression_formats: Option<Vec<String>>,
derive_merge! {
/// TOML representation of how the LLVM build is configured.
#[derive(Deserialize, Default)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Llvm {
skip_rebuild: Option<bool>,
optimize: Option<bool>,
thin_lto: Option<bool>,
release_debuginfo: Option<bool>,
assertions: Option<bool>,
tests: Option<bool>,
plugins: Option<bool>,
ccache: Option<StringOrBool>,
version_check: Option<bool>,
static_libstdcpp: Option<bool>,
ninja: Option<bool>,
targets: Option<String>,
experimental_targets: Option<String>,
link_jobs: Option<u32>,
link_shared: Option<bool>,
version_suffix: Option<String>,
clang_cl: Option<String>,
cflags: Option<String>,
cxxflags: Option<String>,
ldflags: Option<String>,
use_libcxx: Option<bool>,
use_linker: Option<String>,
allow_old_toolchain: Option<bool>,
polly: Option<bool>,
clang: Option<bool>,
download_ci_llvm: Option<StringOrBool>,
}
}
derive_merge! {
#[derive(Deserialize, Default, Clone)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Dist {
sign_folder: Option<String>,
gpg_password_file: Option<String>,
upload_addr: Option<String>,
src_tarball: Option<bool>,
missing_tools: Option<bool>,
compression_formats: Option<Vec<String>>,
}
}
#[derive(Deserialize)]
......@@ -471,80 +505,84 @@ fn default() -> StringOrBool {
}
}
/// TOML representation of how the Rust build is configured.
#[derive(Deserialize, Default, Merge)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Rust {
optimize: Option<bool>,
debug: Option<bool>,
codegen_units: Option<u32>,
codegen_units_std: Option<u32>,
debug_assertions: Option<bool>,
debug_assertions_std: Option<bool>,
overflow_checks: Option<bool>,
overflow_checks_std: Option<bool>,
debug_logging: Option<bool>,
debuginfo_level: Option<u32>,
debuginfo_level_rustc: Option<u32>,
debuginfo_level_std: Option<u32>,
debuginfo_level_tools: Option<u32>,
debuginfo_level_tests: Option<u32>,
run_dsymutil: Option<bool>,
backtrace: Option<bool>,
incremental: Option<bool>,
parallel_compiler: Option<bool>,
default_linker: Option<String>,
channel: Option<String>,
description: Option<String>,
musl_root: Option<String>,
rpath: Option<bool>,
verbose_tests: Option<bool>,
optimize_tests: Option<bool>,
codegen_tests: Option<bool>,
ignore_git: Option<bool>,
dist_src: Option<bool>,
save_toolstates: Option<String>,
codegen_backends: Option<Vec<String>>,
lld: Option<bool>,
use_lld: Option<bool>,
llvm_tools: Option<bool>,
deny_warnings: Option<bool>,
backtrace_on_ice: Option<bool>,
verify_llvm_ir: Option<bool>,
thin_lto_import_instr_limit: Option<u32>,
remap_debuginfo: Option<bool>,
jemalloc: Option<bool>,
test_compare_mode: Option<bool>,
llvm_libunwind: Option<String>,
control_flow_guard: Option<bool>,
new_symbol_mangling: Option<bool>,
profile_generate: Option<String>,
profile_use: Option<String>,
// ignored; this is set from an env var set by bootstrap.py
download_rustc: Option<StringOrBool>,
derive_merge! {
/// TOML representation of how the Rust build is configured.
#[derive(Deserialize, Default)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct Rust {
optimize: Option<bool>,
debug: Option<bool>,
codegen_units: Option<u32>,
codegen_units_std: Option<u32>,
debug_assertions: Option<bool>,
debug_assertions_std: Option<bool>,
overflow_checks: Option<bool>,
overflow_checks_std: Option<bool>,
debug_logging: Option<bool>,
debuginfo_level: Option<u32>,
debuginfo_level_rustc: Option<u32>,
debuginfo_level_std: Option<u32>,
debuginfo_level_tools: Option<u32>,
debuginfo_level_tests: Option<u32>,
run_dsymutil: Option<bool>,
backtrace: Option<bool>,
incremental: Option<bool>,
parallel_compiler: Option<bool>,
default_linker: Option<String>,
channel: Option<String>,
description: Option<String>,
musl_root: Option<String>,
rpath: Option<bool>,
verbose_tests: Option<bool>,
optimize_tests: Option<bool>,
codegen_tests: Option<bool>,
ignore_git: Option<bool>,
dist_src: Option<bool>,
save_toolstates: Option<String>,
codegen_backends: Option<Vec<String>>,
lld: Option<bool>,
use_lld: Option<bool>,
llvm_tools: Option<bool>,
deny_warnings: Option<bool>,
backtrace_on_ice: Option<bool>,
verify_llvm_ir: Option<bool>,
thin_lto_import_instr_limit: Option<u32>,
remap_debuginfo: Option<bool>,
jemalloc: Option<bool>,
test_compare_mode: Option<bool>,
llvm_libunwind: Option<String>,
control_flow_guard: Option<bool>,
new_symbol_mangling: Option<bool>,
profile_generate: Option<String>,
profile_use: Option<String>,
// ignored; this is set from an env var set by bootstrap.py
download_rustc: Option<StringOrBool>,
}
}
/// TOML representation of how each build target is configured.
#[derive(Deserialize, Default, Merge)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct TomlTarget {
cc: Option<String>,
cxx: Option<String>,
ar: Option<String>,
ranlib: Option<String>,
default_linker: Option<PathBuf>,
linker: Option<String>,
llvm_config: Option<String>,
llvm_filecheck: Option<String>,
android_ndk: Option<String>,
sanitizers: Option<bool>,
profiler: Option<bool>,
crt_static: Option<bool>,
musl_root: Option<String>,
musl_libdir: Option<String>,
wasi_root: Option<String>,
qemu_rootfs: Option<String>,
no_std: Option<bool>,
derive_merge! {
/// TOML representation of how each build target is configured.
#[derive(Deserialize, Default)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
struct TomlTarget {
cc: Option<String>,
cxx: Option<String>,
ar: Option<String>,
ranlib: Option<String>,
default_linker: Option<PathBuf>,
linker: Option<String>,
llvm_config: Option<String>,
llvm_filecheck: Option<String>,
android_ndk: Option<String>,
sanitizers: Option<bool>,
profiler: Option<bool>,
crt_static: Option<bool>,
musl_root: Option<String>,
musl_libdir: Option<String>,
wasi_root: Option<String>,
qemu_rootfs: Option<String>,
no_std: Option<bool>,
}
}
impl Config {
......@@ -1111,10 +1149,6 @@ pub fn verbose(&self) -> bool {
self.verbose > 0
}
pub fn very_verbose(&self) -> bool {
self.verbose > 1
}
pub fn sanitizers_enabled(&self, target: TargetSelection) -> bool {
self.target_config.get(&target).map(|t| t.sanitizers).flatten().unwrap_or(self.sanitizers)
}
......
// Various utilities for working with dylib paths.
//
// This file is meant to be included directly to avoid a dependency on the bootstrap library from
// the rustc and rustdoc wrappers. This improves compilation time by reducing the linking time.
/// Returns the environment variable which the dynamic library lookup path
/// resides in for this platform.
pub fn dylib_path_var() -> &'static str {
if cfg!(target_os = "windows") {
"PATH"
} else if cfg!(target_os = "macos") {
"DYLD_LIBRARY_PATH"
} else if cfg!(target_os = "haiku") {
"LIBRARY_PATH"
} else {
"LD_LIBRARY_PATH"
}
}
/// Parses the `dylib_path_var()` environment variable, returning a list of
/// paths that are members of this lookup path.
pub fn dylib_path() -> Vec<PathBuf> {
let var = match env::var_os(dylib_path_var()) {
Some(v) => v,
None => return vec![],
};
env::split_paths(&var).collect()
}
......@@ -110,7 +110,6 @@
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::process::{self, Command};
use std::slice;
use std::str;
#[cfg(unix)]
......@@ -472,10 +471,6 @@ pub fn new(config: Config) -> Build {
build
}
pub fn build_triple(&self) -> &[Interned<String>] {
slice::from_ref(&self.build.triple)
}
// modified from `check_submodule` and `update_submodule` in bootstrap.py
/// Given a path to the directory of a submodule, update it.
///
......
......@@ -16,11 +16,6 @@
use crate::builder::Builder;
use crate::config::{Config, TargetSelection};
/// Returns the `name` as the filename of a static library for `target`.
pub fn staticlib(name: &str, target: TargetSelection) -> String {
if target.contains("windows") { format!("{}.lib", name) } else { format!("lib{}.a", name) }
}
/// Given an executable called `name`, return the filename for the
/// executable for a particular target.
pub fn exe(name: &str, target: TargetSelection) -> String {
......@@ -54,29 +49,7 @@ pub fn add_dylib_path(path: Vec<PathBuf>, cmd: &mut Command) {
cmd.env(dylib_path_var(), t!(env::join_paths(list)));
}
/// Returns the environment variable which the dynamic library lookup path
/// resides in for this platform.
pub fn dylib_path_var() -> &'static str {
if cfg!(target_os = "windows") {
"PATH"
} else if cfg!(target_os = "macos") {
"DYLD_LIBRARY_PATH"
} else if cfg!(target_os = "haiku") {
"LIBRARY_PATH"
} else {
"LD_LIBRARY_PATH"
}
}
/// Parses the `dylib_path_var()` environment variable, returning a list of
/// paths that are members of this lookup path.
pub fn dylib_path() -> Vec<PathBuf> {
let var = match env::var_os(dylib_path_var()) {
Some(v) => v,
None => return vec![],
};
env::split_paths(&var).collect()
}
include!("dylib_util.rs");
/// Adds a list of lookup paths to `cmd`'s link library lookup path.
pub fn add_link_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
......@@ -103,21 +76,6 @@ fn link_lib_path() -> Vec<PathBuf> {
env::split_paths(&var).collect()
}
/// `push` all components to `buf`. On windows, append `.exe` to the last component.
pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf {
let (&file, components) = components.split_last().expect("at least one component required");
let mut file = file.to_owned();
if cfg!(windows) {
file.push_str(".exe");
}
buf.extend(components);
buf.push(file);
buf
}
pub struct TimeIt(bool, Instant);
/// Returns an RAII structure that prints out how long it took to drop.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册