From 842151328a4cb887203b27a011a66925c08a0e00 Mon Sep 17 00:00:00 2001 From: Alex Huszagh Date: Fri, 10 Jun 2022 23:30:35 -0500 Subject: [PATCH] Add build-std config option. Detects if `rust-std` is not an available component for a target, and if `build-std = true` in `Cross.toml` under `[build]` or `[target.(...)]`, then use the `-Zbuild-std` flag. This has higher priority than `xargo`: `xargo` will only be used if a target is not a built-in. A sample `Cross.toml` file is the following: ```toml [target.x86_64-unknown-dragonfly] build-std = true ``` Closes #692. --- CHANGELOG.md | 1 + docs/cross_toml.md | 4 +++- src/config.rs | 18 +++++++++++++++++- src/cross_toml.rs | 11 +++++++++++ src/lib.rs | 17 ++++++++++++++--- 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ffda65ed..5771c162b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- #782 - added `build-std` config option, which builds the rust standard library from source if enabled. - #775 - forward Cargo exit code to host - #767 - added the `cross-util` and `cross-dev` commands. - #745 - added `thumbv7neon-*` targets. diff --git a/docs/cross_toml.md b/docs/cross_toml.md index 662c541af..16f306886 100644 --- a/docs/cross_toml.md +++ b/docs/cross_toml.md @@ -6,6 +6,7 @@ The `build` key allows you to set global variables, e.g.: ```toml [build] xargo = true +build-std = true default-target = "x86_64-unknown-linux-gnu" ``` @@ -26,6 +27,7 @@ The `target` key allows you to specify parameters for specific compilation targe ```toml [target.aarch64-unknown-linux-gnu] xargo = false +build-std = false image = "test-image" runner = "custom-runner" ``` @@ -38,4 +40,4 @@ This is similar to `build.env`, but allows you to be more specific per target. [target.x86_64-unknown-linux-gnu.env] volumes = ["VOL1_ARG", "VOL2_ARG"] passthrough = ["IMPORTANT_ENV_VARIABLES"] -``` \ No newline at end of file +``` diff --git a/src/config.rs b/src/config.rs index c25d3957e..7523b2add 100644 --- a/src/config.rs +++ b/src/config.rs @@ -41,7 +41,11 @@ impl Environment { } fn build_path(key: &str) -> String { - format!("BUILD_{key}") + if !key.starts_with("BUILD_") { + format!("BUILD_{key}") + } else { + key.to_string() + } } fn get_build_var(&self, key: &str) -> Option { @@ -56,6 +60,10 @@ impl Environment { self.get_values_for("XARGO", target, bool_from_envvar) } + fn build_std(&self, target: &Target) -> (Option, Option) { + self.get_values_for("BUILD_STD", target, bool_from_envvar) + } + fn image(&self, target: &Target) -> Option { self.get_target_var(target, "IMAGE") } @@ -191,6 +199,10 @@ impl Config { self.bool_from_config(target, Environment::xargo, CrossToml::xargo) } + pub fn build_std(&self, target: &Target) -> Option { + self.bool_from_config(target, Environment::build_std, CrossToml::build_std) + } + pub fn image(&self, target: &Target) -> Result> { self.string_from_config(target, Environment::image, CrossToml::image) } @@ -270,9 +282,11 @@ mod tests { pub fn parse_error_in_env() { let mut map = std::collections::HashMap::new(); map.insert("CROSS_BUILD_XARGO", "tru"); + map.insert("CROSS_BUILD_STD", "false"); let env = Environment::new(Some(map)); assert_eq!(env.xargo(&target()), (Some(true), None)); + assert_eq!(env.build_std(&target()), (Some(false), None)); } #[test] @@ -346,10 +360,12 @@ mod tests { pub fn env_target_and_toml_target_xargo_target_then_use_env() -> Result<()> { let mut map = HashMap::new(); map.insert("CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO", "true"); + map.insert("CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_BUILD_STD", "true"); let env = Environment::new(Some(map)); let config = Config::new_with(Some(toml(TOML_TARGET_XARGO_FALSE)?), env); assert!(matches!(config.xargo(&target()), Some(true))); + assert!(matches!(config.build_std(&target()), Some(true))); Ok(()) } diff --git a/src/cross_toml.rs b/src/cross_toml.rs index af05d0d4b..1c125b505 100644 --- a/src/cross_toml.rs +++ b/src/cross_toml.rs @@ -21,13 +21,16 @@ pub struct CrossBuildConfig { #[serde(default)] env: CrossEnvConfig, xargo: Option, + build_std: Option, default_target: Option, } /// Target configuration #[derive(Debug, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] pub struct CrossTargetConfig { xargo: Option, + build_std: Option, image: Option, runner: Option, #[serde(default)] @@ -79,6 +82,11 @@ impl CrossToml { self.get_bool(target, |b| b.xargo, |t| t.xargo) } + /// Returns the `build.build-std` or the `target.{}.build-std` part of `Cross.toml` + pub fn build_std(&self, target: &Target) -> (Option, Option) { + self.get_bool(target, |b| b.build_std, |t| t.build_std) + } + /// Returns the list of environment variables to pass through for `build`, pub fn env_passthrough_build(&self) -> &[String] { &self.build.env.passthrough @@ -165,6 +173,7 @@ mod tests { passthrough: vec!["VAR1".to_string(), "VAR2".to_string()], }, xargo: Some(true), + build_std: None, default_target: None, }, }; @@ -198,6 +207,7 @@ mod tests { volumes: vec!["VOL1_ARG".to_string(), "VOL2_ARG".to_string()], }, xargo: Some(false), + build_std: Some(true), image: Some("test-image".to_string()), runner: None, }, @@ -214,6 +224,7 @@ mod tests { passthrough = ["VAR1", "VAR2"] [target.aarch64-unknown-linux-gnu] xargo = false + build-std = true image = "test-image" "#; let (parsed_cfg, unused) = CrossToml::parse(test_str)?; diff --git a/src/lib.rs b/src/lib.rs index f4642c6ff..4805ff365 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -348,10 +348,18 @@ pub fn run() -> Result { is_nightly = channel == Channel::Nightly; } + // build-std overrides xargo, but only use it if it's a built-in + // tool but not an available target or doesn't have rust-std. let available_targets = rustup::available_targets(&toolchain, verbose)?; - let uses_xargo = config - .xargo(&target) - .unwrap_or_else(|| !target.is_builtin() || !available_targets.contains(&target)); + let uses_build_std = config.build_std(&target).unwrap_or(false); + let uses_xargo = + !uses_build_std && config.xargo(&target).unwrap_or(!target.is_builtin()); + if !is_nightly && uses_build_std { + eyre::bail!( + "no rust-std component available for {}: must use nightly", + target.triple() + ); + } if !uses_xargo && !available_targets.is_installed(&target) @@ -409,6 +417,9 @@ pub fn run() -> Result { if is_test && args.enable_doctests && is_nightly { filtered_args.push("-Zdoctest-xcompile".to_string()); } + if uses_build_std { + filtered_args.push("-Zbuild-std".to_string()); + } if target.needs_docker() && args.subcommand.map(|sc| sc.needs_docker()).unwrap_or(false) {