diff options
| -rw-r--r-- | Cargo.lock | 24 | ||||
| -rw-r--r-- | src/bootstrap/Cargo.toml | 2 | ||||
| -rw-r--r-- | src/bootstrap/bin/rustc.rs | 8 | ||||
| -rw-r--r-- | src/bootstrap/bin/rustdoc.rs | 8 | ||||
| -rw-r--r-- | src/bootstrap/builder.rs | 3 | ||||
| -rw-r--r-- | src/bootstrap/cache.rs | 7 | ||||
| -rw-r--r-- | src/bootstrap/config.rs | 374 | ||||
| -rw-r--r-- | src/bootstrap/dylib_util.rs | 28 | ||||
| -rw-r--r-- | src/bootstrap/lib.rs | 5 | ||||
| -rw-r--r-- | src/bootstrap/util.rs | 44 |
10 files changed, 247 insertions, 256 deletions
diff --git a/Cargo.lock b/Cargo.lock index 959c8161e98..a912eee97db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,9 +175,7 @@ dependencies = [ "filetime", "getopts", "ignore", - "lazy_static", "libc", - "merge", "num_cpus", "once_cell", "opener", @@ -2222,28 +2220,6 @@ dependencies = [ ] [[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" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 1ce1f0b26db..b68b2163f87 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -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] diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index ed53a98e9a5..7105a2457e2 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -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, ); diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index e4396d53016..ad3800834b0 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -7,6 +7,8 @@ use std::ffi::OsString; 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, ); diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index bbd2c087cca..917abde9de1 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -351,7 +351,6 @@ pub enum Kind { Check, Clippy, Fix, - Format, Test, Bench, Dist, @@ -399,7 +398,7 @@ impl<'a> Builder<'a> { 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, diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 0c16fae01bc..fac5d8db511 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -13,7 +13,8 @@ use std::ops::Deref; 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 @@ impl Interner { } } -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, diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 7a4593a75f2..5af9248583c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -18,7 +18,6 @@ pub use crate::flags::Subcommand; 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 @@ impl Merge for TomlConfig { } } -/// 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 @@ impl Default for 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 @@ impl Config { 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) } diff --git a/src/bootstrap/dylib_util.rs b/src/bootstrap/dylib_util.rs new file mode 100644 index 00000000000..6d75272c501 --- /dev/null +++ b/src/bootstrap/dylib_util.rs @@ -0,0 +1,28 @@ +// 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() +} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 82462f9758e..8569089f701 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -110,7 +110,6 @@ 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(unix)] @@ -472,10 +471,6 @@ impl 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. /// diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 57178aa382f..ee58bedcc87 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -16,11 +16,6 @@ use build_helper::t; 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. |
