Add sample defaults for config.toml
- Allow including defaults in `src/bootstrap/defaults` using `profile = "..."` - Add default config files - Combine config files using the merge dependency. - Add comments to default config files - Add a README asking to open an issue if the defaults are bad - Give a loud error if trying to merge `.target`, since it's not currently supported - Use an exhaustive match - Use `<none>` in config.toml.example to avoid confusion - Fix bugs in `Merge` derives Previously, it would completely ignore the profile defaults if there were any settings in `config.toml`. I sent an email to the `merge` maintainer asking them to make the behavior in this commit the default. This introduces a new dependency on `merge` that hasn't yet been vetted. I want to improve the output when `include = "x"` isn't found: ``` thread 'main' panicked at 'fs::read_to_string(&file) failed with No such file or directory (os error 2) ("configuration file did not exist")', src/bootstrap/config.rs:522:28 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failed to run: /home/joshua/rustc/build/bootstrap/debug/bootstrap test tidy Build completed unsuccessfully in 0:00:00 ``` However that seems like it could be fixed in a follow-up.
This commit is contained in:
parent
7bdb5dee7b
commit
c9c8fb88cf
23
Cargo.lock
23
Cargo.lock
|
@ -207,6 +207,7 @@ dependencies = [
|
||||||
"ignore",
|
"ignore",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
"merge",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"opener",
|
"opener",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
|
@ -1900,6 +1901,28 @@ dependencies = [
|
||||||
"autocfg",
|
"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]]
|
[[package]]
|
||||||
name = "minifier"
|
name = "minifier"
|
||||||
version = "0.0.33"
|
version = "0.0.33"
|
||||||
|
|
|
@ -9,6 +9,16 @@
|
||||||
# a custom configuration file can also be specified with `--config` to the build
|
# a custom configuration file can also be specified with `--config` to the build
|
||||||
# system.
|
# system.
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Global Settings
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Use different pre-set defaults than the global defaults.
|
||||||
|
#
|
||||||
|
# See `src/bootstrap/defaults` for more information.
|
||||||
|
# Note that this has no default value (x.py uses the defaults in `config.toml.example`).
|
||||||
|
#profile = <none>
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Tweaking how LLVM is compiled
|
# Tweaking how LLVM is compiled
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
|
@ -48,6 +48,7 @@ lazy_static = "1.3.0"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
ignore = "0.4.10"
|
ignore = "0.4.10"
|
||||||
opener = "0.4"
|
opener = "0.4"
|
||||||
|
merge = "0.1.0"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies.winapi]
|
[target.'cfg(windows)'.dependencies.winapi]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
|
|
|
@ -16,6 +16,7 @@ use crate::flags::Flags;
|
||||||
pub use crate::flags::Subcommand;
|
pub use crate::flags::Subcommand;
|
||||||
use crate::util::exe;
|
use crate::util::exe;
|
||||||
use build_helper::t;
|
use build_helper::t;
|
||||||
|
use merge::Merge;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
macro_rules! check_ci_llvm {
|
macro_rules! check_ci_llvm {
|
||||||
|
@ -278,10 +279,31 @@ struct TomlConfig {
|
||||||
rust: Option<Rust>,
|
rust: Option<Rust>,
|
||||||
target: Option<HashMap<String, TomlTarget>>,
|
target: Option<HashMap<String, TomlTarget>>,
|
||||||
dist: Option<Dist>,
|
dist: Option<Dist>,
|
||||||
|
profile: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Merge for TomlConfig {
|
||||||
|
fn merge(&mut self, TomlConfig { build, install, llvm, rust, dist, target, profile: _ }: Self) {
|
||||||
|
fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>) {
|
||||||
|
if let Some(new) = y {
|
||||||
|
if let Some(original) = x {
|
||||||
|
original.merge(new);
|
||||||
|
} else {
|
||||||
|
*x = Some(new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
do_merge(&mut self.build, build);
|
||||||
|
do_merge(&mut self.install, install);
|
||||||
|
do_merge(&mut self.llvm, llvm);
|
||||||
|
do_merge(&mut self.rust, rust);
|
||||||
|
do_merge(&mut self.dist, dist);
|
||||||
|
assert!(target.is_none(), "merging target-specific config is not currently supported");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TOML representation of various global build decisions.
|
/// TOML representation of various global build decisions.
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||||
struct Build {
|
struct Build {
|
||||||
build: Option<String>,
|
build: Option<String>,
|
||||||
|
@ -321,7 +343,7 @@ struct Build {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TOML representation of various global install decisions.
|
/// TOML representation of various global install decisions.
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||||
struct Install {
|
struct Install {
|
||||||
prefix: Option<String>,
|
prefix: Option<String>,
|
||||||
|
@ -338,7 +360,7 @@ struct Install {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TOML representation of how the LLVM build is configured.
|
/// TOML representation of how the LLVM build is configured.
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||||
struct Llvm {
|
struct Llvm {
|
||||||
skip_rebuild: Option<bool>,
|
skip_rebuild: Option<bool>,
|
||||||
|
@ -365,7 +387,7 @@ struct Llvm {
|
||||||
download_ci_llvm: Option<bool>,
|
download_ci_llvm: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Clone)]
|
#[derive(Deserialize, Default, Clone, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||||
struct Dist {
|
struct Dist {
|
||||||
sign_folder: Option<String>,
|
sign_folder: Option<String>,
|
||||||
|
@ -389,7 +411,7 @@ impl Default for StringOrBool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TOML representation of how the Rust build is configured.
|
/// TOML representation of how the Rust build is configured.
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||||
struct Rust {
|
struct Rust {
|
||||||
optimize: Option<bool>,
|
optimize: Option<bool>,
|
||||||
|
@ -434,7 +456,7 @@ struct Rust {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TOML representation of how each build target is configured.
|
/// TOML representation of how each build target is configured.
|
||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||||
struct TomlTarget {
|
struct TomlTarget {
|
||||||
cc: Option<String>,
|
cc: Option<String>,
|
||||||
|
@ -523,27 +545,31 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
let toml = TomlConfig::default();
|
let get_toml = |_| TomlConfig::default();
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
let toml = flags
|
let get_toml = |file: PathBuf| {
|
||||||
.config
|
use std::process;
|
||||||
.map(|file| {
|
|
||||||
use std::process;
|
|
||||||
|
|
||||||
let contents = t!(fs::read_to_string(&file));
|
let contents = t!(fs::read_to_string(&file), "configuration file did not exist");
|
||||||
match toml::from_str(&contents) {
|
match toml::from_str(&contents) {
|
||||||
Ok(table) => table,
|
Ok(table) => table,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!(
|
println!("failed to parse TOML configuration '{}': {}", file.display(), err);
|
||||||
"failed to parse TOML configuration '{}': {}",
|
process::exit(2);
|
||||||
file.display(),
|
|
||||||
err
|
|
||||||
);
|
|
||||||
process::exit(2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.unwrap_or_else(TomlConfig::default);
|
};
|
||||||
|
|
||||||
|
let mut toml = flags.config.map(get_toml).unwrap_or_else(TomlConfig::default);
|
||||||
|
if let Some(include) = &toml.profile {
|
||||||
|
let mut include_path = config.src.clone();
|
||||||
|
include_path.push("src");
|
||||||
|
include_path.push("bootstrap");
|
||||||
|
include_path.push("defaults");
|
||||||
|
include_path.push(format!("config.toml.{}", include));
|
||||||
|
let included_toml = get_toml(include_path);
|
||||||
|
toml.merge(included_toml);
|
||||||
|
}
|
||||||
|
|
||||||
let build = toml.build.unwrap_or_default();
|
let build = toml.build.unwrap_or_default();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
# About bootstrap defaults
|
||||||
|
|
||||||
|
These defaults are intended to be a good starting point for working with x.py,
|
||||||
|
with the understanding that no one set of defaults make sense for everyone.
|
||||||
|
|
||||||
|
They are still experimental, and we'd appreciate your help improving them!
|
||||||
|
If you use a setting that's not in these defaults that you think others would benefit from, please [file an issue] or make a PR with the changes.
|
||||||
|
Similarly, if one of these defaults doesn't match what you use personally,
|
||||||
|
please open an issue to get it changed.
|
||||||
|
|
||||||
|
[file an issue]: https://github.com/rust-lang/rust/issues/new/choose
|
|
@ -0,0 +1,13 @@
|
||||||
|
# These defaults are meant for contributors to the compiler who modify codegen or LLVM
|
||||||
|
[llvm]
|
||||||
|
# This enables debug-assertions in LLVM,
|
||||||
|
# catching logic errors in codegen much earlier in the process.
|
||||||
|
assertions = true
|
||||||
|
|
||||||
|
[rust]
|
||||||
|
# This enables `RUSTC_LOG=debug`, avoiding confusing situations
|
||||||
|
# where adding `debug!()` appears to do nothing.
|
||||||
|
# However, it makes running the compiler slightly slower.
|
||||||
|
debug-logging = true
|
||||||
|
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
|
||||||
|
incremental = true
|
|
@ -0,0 +1,8 @@
|
||||||
|
# These defaults are meant for contributors to the compiler who do not modify codegen or LLVM
|
||||||
|
[rust]
|
||||||
|
# This enables `RUSTC_LOG=debug`, avoiding confusing situations
|
||||||
|
# where adding `debug!()` appears to do nothing.
|
||||||
|
# However, it makes running the compiler slightly slower.
|
||||||
|
debug-logging = true
|
||||||
|
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
|
||||||
|
incremental = true
|
|
@ -0,0 +1,10 @@
|
||||||
|
# These defaults are meant for contributors to the standard library and documentation.
|
||||||
|
[build]
|
||||||
|
# When building the standard library, you almost never want to build the compiler itself.
|
||||||
|
build-stage = 0
|
||||||
|
test-stage = 0
|
||||||
|
bench-stage = 0
|
||||||
|
|
||||||
|
[rust]
|
||||||
|
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
|
||||||
|
incremental = true
|
|
@ -0,0 +1,9 @@
|
||||||
|
# These defaults are meant for users and distro maintainers building from source, without intending to make multiple changes.
|
||||||
|
[build]
|
||||||
|
# When compiling from source, you almost always want a full stage 2 build,
|
||||||
|
# which has all the latest optimizations from nightly.
|
||||||
|
build-stage = 2
|
||||||
|
test-stage = 2
|
||||||
|
doc-stage = 2
|
||||||
|
# When compiling from source, you usually want all tools.
|
||||||
|
extended = true
|
Loading…
Reference in New Issue