Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow build-std to take an array of crate names #1488

Merged
merged 1 commit into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/1488.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"description": "Allow `build-std` to take an array of crate names",
"issues": [896],
"type": "changed",
"breaking": true
}
8 changes: 4 additions & 4 deletions docs/config_file.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,10 @@ targets:

```toml
[target.aarch64-unknown-linux-gnu]
build-std = false # always build the std library. has precedence over xargo
xargo = false # disable the use of xargo
image = "test-image" # use a different image for the target
runner = "qemu-user" # wrapper to run the binary (must be `qemu-system`, `qemu-user`, or `native`).
build-std = ["core", "alloc"] # always build the `core` and `alloc` crates from the std library. has precedence over xargo
xargo = false # disable the use of xargo
image = "test-image" # use a different image for the target
runner = "qemu-user" # wrapper to run the binary (must be `qemu-system`, `qemu-user`, or `native`).
```


Expand Down
41 changes: 29 additions & 12 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::cross_toml::BuildStd;
use crate::docker::custom::PreBuild;
use crate::docker::{ImagePlatform, PossibleImage};
use crate::shell::MessageInfo;
Expand Down Expand Up @@ -63,8 +64,14 @@ impl Environment {
self.get_values_for("XARGO", target, bool_from_envvar)
}

fn build_std(&self, target: &Target) -> (Option<bool>, Option<bool>) {
self.get_values_for("BUILD_STD", target, bool_from_envvar)
fn build_std(&self, target: &Target) -> (Option<BuildStd>, Option<BuildStd>) {
self.get_values_for("BUILD_STD", target, |v| {
if let Some(value) = try_bool_from_envvar(v) {
BuildStd::Bool(value)
} else {
BuildStd::Crates(v.split(',').map(str::to_owned).collect())
}
})
}

fn zig(&self, target: &Target) -> (Option<bool>, Option<bool>) {
Expand Down Expand Up @@ -189,12 +196,16 @@ fn split_to_cloned_by_ws(string: &str) -> Vec<String> {
/// this takes the value of the environment variable,
/// so you should call `bool_from_envvar(env::var("FOO"))`
pub fn bool_from_envvar(envvar: &str) -> bool {
try_bool_from_envvar(envvar).unwrap_or(!envvar.is_empty())
}

pub fn try_bool_from_envvar(envvar: &str) -> Option<bool> {
if let Ok(value) = bool::from_str(envvar) {
value
Some(value)
} else if let Ok(value) = i32::from_str(envvar) {
value != 0
Some(value != 0)
} else {
!envvar.is_empty()
None
}
}

Expand Down Expand Up @@ -350,8 +361,8 @@ impl Config {
self.bool_from_config(target, Environment::xargo, CrossToml::xargo)
}

pub fn build_std(&self, target: &Target) -> Option<bool> {
self.bool_from_config(target, Environment::build_std, CrossToml::build_std)
pub fn build_std(&self, target: &Target) -> Result<Option<BuildStd>> {
self.get_from_ref(target, Environment::build_std, CrossToml::build_std)
}

pub fn zig(&self, target: &Target) -> Option<bool> {
Expand Down Expand Up @@ -531,7 +542,10 @@ mod tests {

let env = Environment::new(Some(map));
assert_eq!(env.xargo(&target()), (Some(true), None));
assert_eq!(env.build_std(&target()), (Some(false), None));
assert_eq!(
env.build_std(&target()),
(Some(BuildStd::Bool(false)), None)
);
assert_eq!(env.zig(&target()), (None, None));
assert_eq!(env.zig_version(&target()), (None, None));
assert_eq!(env.zig_image(&target())?, (Some("zig:local".into()), None));
Expand Down Expand Up @@ -621,7 +635,7 @@ mod tests {
let env = Environment::new(Some(map));
let config = Config::new_with(Some(toml(TOML_BUILD_XARGO_FALSE)?), env);
assert_eq!(config.xargo(&target()), Some(true));
assert_eq!(config.build_std(&target()), None);
assert_eq!(config.build_std(&target())?, None);
assert_eq!(
config.pre_build(&target())?,
Some(PreBuild::Lines(vec![
Expand All @@ -637,12 +651,15 @@ 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");
map.insert("CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_BUILD_STD", "core");
let env = Environment::new(Some(map));

let config = Config::new_with(Some(toml(TOML_TARGET_XARGO_FALSE)?), env);
assert_eq!(config.xargo(&target()), Some(true));
assert_eq!(config.build_std(&target()), Some(true));
assert_eq!(
config.build_std(&target())?,
Some(BuildStd::Crates(vec!["core".to_owned()]))
);
assert_eq!(config.pre_build(&target())?, None);

Ok(())
Expand All @@ -656,7 +673,7 @@ mod tests {
let env = Environment::new(Some(map));
let config = Config::new_with(Some(toml(TOML_BUILD_XARGO_FALSE)?), env);
assert_eq!(config.xargo(&target()), Some(true));
assert_eq!(config.build_std(&target()), None);
assert_eq!(config.build_std(&target())?, None);
assert_eq!(config.pre_build(&target())?, None);

Ok(())
Expand Down
50 changes: 39 additions & 11 deletions src/cross_toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub struct CrossBuildConfig {
#[serde(default)]
env: CrossEnvConfig,
xargo: Option<bool>,
build_std: Option<bool>,
build_std: Option<BuildStd>,
#[serde(default, deserialize_with = "opt_string_bool_or_struct")]
zig: Option<CrossZigConfig>,
default_target: Option<String>,
Expand All @@ -44,7 +44,7 @@ pub struct CrossBuildConfig {
#[serde(rename_all = "kebab-case")]
pub struct CrossTargetConfig {
xargo: Option<bool>,
build_std: Option<bool>,
build_std: Option<BuildStd>,
#[serde(default, deserialize_with = "opt_string_bool_or_struct")]
zig: Option<CrossZigConfig>,
#[serde(default, deserialize_with = "opt_string_or_struct")]
Expand All @@ -58,6 +58,28 @@ pub struct CrossTargetConfig {
env: CrossEnvConfig,
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
#[serde(untagged, rename_all = "kebab-case")]
pub enum BuildStd {
Bool(bool),
Crates(Vec<String>),
}

impl Default for BuildStd {
fn default() -> Self {
Self::Bool(false)
}
}

impl BuildStd {
pub fn enabled(&self) -> bool {
match self {
Self::Bool(enabled) => *enabled,
Self::Crates(arr) => !arr.is_empty(),
}
}
}

/// Dockerfile configuration
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
Expand Down Expand Up @@ -306,8 +328,8 @@ impl CrossToml {
}

/// Returns the `build.build-std` or the `target.{}.build-std` part of `Cross.toml`
pub fn build_std(&self, target: &Target) -> (Option<bool>, Option<bool>) {
self.get_value(target, |b| b.build_std, |t| t.build_std)
pub fn build_std(&self, target: &Target) -> (Option<&BuildStd>, Option<&BuildStd>) {
self.get_ref(target, |b| b.build_std.as_ref(), |t| t.build_std.as_ref())
}

/// Returns the `{}.zig` or `{}.zig.version` part of `Cross.toml`
Expand Down Expand Up @@ -647,7 +669,7 @@ mod tests {
volumes: Some(vec![p!("VOL1_ARG"), p!("VOL2_ARG")]),
},
xargo: Some(false),
build_std: Some(true),
build_std: Some(BuildStd::Bool(true)),
zig: None,
image: Some("test-image".into()),
runner: None,
Expand Down Expand Up @@ -923,7 +945,7 @@ mod tests {
passthrough = ["VAR3"]

[build]
build-std = true
build-std = ["core", "alloc"]
xargo = false
default-target = "aarch64-unknown-linux-gnu"

Expand Down Expand Up @@ -962,7 +984,7 @@ mod tests {
passthrough = ["VAR3"]

[build]
build-std = true
build-std = ["core", "alloc"]
xargo = false
default-target = "aarch64-unknown-linux-gnu"

Expand All @@ -983,7 +1005,13 @@ mod tests {
// need to test individual values. i've broken this down into
// tests on values for better error reporting
let build = &cfg_expected.build;
assert_eq!(build.build_std, Some(true));
assert_eq!(
build.build_std,
Some(BuildStd::Crates(vec![
"core".to_owned(),
"alloc".to_owned()
]))
);
assert_eq!(build.xargo, Some(false));
assert_eq!(build.default_target, Some(p!("aarch64-unknown-linux-gnu")));
assert_eq!(build.pre_build, None);
Expand All @@ -993,7 +1021,7 @@ mod tests {

let targets = &cfg_expected.targets;
let aarch64 = &targets[&Target::new_built_in("aarch64-unknown-linux-gnu")];
assert_eq!(aarch64.build_std, Some(true));
assert_eq!(aarch64.build_std, Some(BuildStd::Bool(true)));
assert_eq!(aarch64.xargo, Some(false));
assert_eq!(aarch64.image, Some(p!("test-image1")));
assert_eq!(aarch64.pre_build, None);
Expand All @@ -1002,7 +1030,7 @@ mod tests {
assert_eq!(aarch64.env.volumes, Some(vec![p!("VOL1_ARG")]));

let target2 = &targets[&Target::new_custom("target2")];
assert_eq!(target2.build_std, Some(false));
assert_eq!(target2.build_std, Some(BuildStd::Bool(false)));
assert_eq!(target2.xargo, Some(false));
assert_eq!(target2.image, Some(p!("test-image2-precedence")));
assert_eq!(target2.pre_build, None);
Expand All @@ -1011,7 +1039,7 @@ mod tests {
assert_eq!(target2.env.volumes, Some(vec![p!("VOL2_ARG_PRECEDENCE")]));

let target3 = &targets[&Target::new_custom("target3")];
assert_eq!(target3.build_std, Some(true));
assert_eq!(target3.build_std, Some(BuildStd::Bool(true)));
assert_eq!(target3.xargo, Some(false));
assert_eq!(target3.image, Some(p!("test-image3")));
assert_eq!(target3.pre_build, None);
Expand Down
36 changes: 19 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ use cli::Args;
use color_eyre::owo_colors::OwoColorize;
use color_eyre::{Help, SectionExt};
use config::Config;
use cross_toml::BuildStd;
use rustc::{QualifiedToolchain, Toolchain};
use rustc_version::Channel;
use serde::{Deserialize, Serialize, Serializer};
Expand Down Expand Up @@ -541,7 +542,7 @@ pub fn run(
target,
uses_xargo,
uses_zig,
uses_build_std,
build_std,
zig_version,
toolchain,
is_remote,
Expand Down Expand Up @@ -586,22 +587,16 @@ pub fn run(
rustup::setup_components(
&target,
uses_xargo,
uses_build_std,
build_std.enabled(),
&toolchain,
is_nightly,
available_targets,
&args,
msg_info,
)?;

let filtered_args = get_filtered_args(
zig_version,
&args,
&target,
&config,
is_nightly,
uses_build_std,
);
let filtered_args =
get_filtered_args(zig_version, &args, &target, &config, is_nightly, &build_std);

let needs_docker = args
.subcommand
Expand Down Expand Up @@ -693,7 +688,7 @@ pub fn get_filtered_args(
target: &Target,
config: &Config,
is_nightly: bool,
uses_build_std: bool,
build_std: &BuildStd,
) -> Vec<String> {
let add_libc = |triple: &str| add_libc_version(triple, zig_version.as_deref());
let mut filtered_args = if args
Expand Down Expand Up @@ -746,9 +741,16 @@ pub fn get_filtered_args(
if is_test && config.doctests().unwrap_or_default() && is_nightly {
filtered_args.push("-Zdoctest-xcompile".to_owned());
}
if uses_build_std {
filtered_args.push("-Zbuild-std".to_owned());

if build_std.enabled() {
let mut arg = "-Zbuild-std".to_owned();
if let BuildStd::Crates(crates) = build_std {
arg.push('=');
arg.push_str(&crates.join(","));
}
filtered_args.push(arg);
}

filtered_args.extend(args.rest_args.iter().cloned());
filtered_args
}
Expand All @@ -769,8 +771,8 @@ pub fn setup(
.clone()
.or_else(|| config.target(&target_list))
.unwrap_or_else(|| Target::from(host.triple(), &target_list));
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());
let build_std = config.build_std(&target)?.unwrap_or_default();
let uses_xargo = !build_std.enabled() && config.xargo(&target).unwrap_or(!target.is_builtin());
let uses_zig = config.zig(&target).unwrap_or(false);
let zig_version = config.zig_version(&target)?;
let image = match docker::get_image(&config, &target, uses_zig) {
Expand Down Expand Up @@ -815,7 +817,7 @@ To override the toolchain mounted in the image, set `target.{target}.image.toolc
target,
uses_xargo,
uses_zig,
uses_build_std,
build_std,
zig_version,
toolchain,
is_remote,
Expand All @@ -830,7 +832,7 @@ pub struct CrossSetup {
pub target: Target,
pub uses_xargo: bool,
pub uses_zig: bool,
pub uses_build_std: bool,
pub build_std: BuildStd,
pub zig_version: Option<String>,
pub toolchain: QualifiedToolchain,
pub is_remote: bool,
Expand Down
Loading