Skip to content

Commit e1676d2

Browse files
782: Add build-std config option. r=Emilgardis a=Alexhuszagh 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. Closes cross-rs#692. Co-authored-by: Alex Huszagh <[email protected]>
2 parents cf582ce + 8421513 commit e1676d2

File tree

5 files changed

+46
-5
lines changed

5 files changed

+46
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
77

88
### Added
99

10+
- #782 - added `build-std` config option, which builds the rust standard library from source if enabled.
1011
- #775 - forward Cargo exit code to host
1112
- #772 - added `CROSS_CONTAINER_OPTS` environment variable to replace `DOCKER_OPTS`.
1213
- #767, #788 - added the `cross-util` and `xtask` commands.

docs/cross_toml.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The `build` key allows you to set global variables, e.g.:
66
```toml
77
[build]
88
xargo = true
9+
build-std = true
910
default-target = "x86_64-unknown-linux-gnu"
1011
```
1112

@@ -26,6 +27,7 @@ The `target` key allows you to specify parameters for specific compilation targe
2627
```toml
2728
[target.aarch64-unknown-linux-gnu]
2829
xargo = false
30+
build-std = false
2931
image = "test-image"
3032
runner = "custom-runner"
3133
```
@@ -38,4 +40,4 @@ This is similar to `build.env`, but allows you to be more specific per target.
3840
[target.x86_64-unknown-linux-gnu.env]
3941
volumes = ["VOL1_ARG", "VOL2_ARG"]
4042
passthrough = ["IMPORTANT_ENV_VARIABLES"]
41-
```
43+
```

src/config.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ impl Environment {
4141
}
4242

4343
fn build_path(key: &str) -> String {
44-
format!("BUILD_{key}")
44+
if !key.starts_with("BUILD_") {
45+
format!("BUILD_{key}")
46+
} else {
47+
key.to_string()
48+
}
4549
}
4650

4751
fn get_build_var(&self, key: &str) -> Option<String> {
@@ -56,6 +60,10 @@ impl Environment {
5660
self.get_values_for("XARGO", target, bool_from_envvar)
5761
}
5862

63+
fn build_std(&self, target: &Target) -> (Option<bool>, Option<bool>) {
64+
self.get_values_for("BUILD_STD", target, bool_from_envvar)
65+
}
66+
5967
fn image(&self, target: &Target) -> Option<String> {
6068
self.get_target_var(target, "IMAGE")
6169
}
@@ -191,6 +199,10 @@ impl Config {
191199
self.bool_from_config(target, Environment::xargo, CrossToml::xargo)
192200
}
193201

202+
pub fn build_std(&self, target: &Target) -> Option<bool> {
203+
self.bool_from_config(target, Environment::build_std, CrossToml::build_std)
204+
}
205+
194206
pub fn image(&self, target: &Target) -> Result<Option<String>> {
195207
self.string_from_config(target, Environment::image, CrossToml::image)
196208
}
@@ -270,9 +282,11 @@ mod tests {
270282
pub fn parse_error_in_env() {
271283
let mut map = std::collections::HashMap::new();
272284
map.insert("CROSS_BUILD_XARGO", "tru");
285+
map.insert("CROSS_BUILD_STD", "false");
273286

274287
let env = Environment::new(Some(map));
275288
assert_eq!(env.xargo(&target()), (Some(true), None));
289+
assert_eq!(env.build_std(&target()), (Some(false), None));
276290
}
277291

278292
#[test]
@@ -346,10 +360,12 @@ mod tests {
346360
pub fn env_target_and_toml_target_xargo_target_then_use_env() -> Result<()> {
347361
let mut map = HashMap::new();
348362
map.insert("CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO", "true");
363+
map.insert("CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_BUILD_STD", "true");
349364
let env = Environment::new(Some(map));
350365

351366
let config = Config::new_with(Some(toml(TOML_TARGET_XARGO_FALSE)?), env);
352367
assert!(matches!(config.xargo(&target()), Some(true)));
368+
assert!(matches!(config.build_std(&target()), Some(true)));
353369

354370
Ok(())
355371
}

src/cross_toml.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ pub struct CrossBuildConfig {
2121
#[serde(default)]
2222
env: CrossEnvConfig,
2323
xargo: Option<bool>,
24+
build_std: Option<bool>,
2425
default_target: Option<String>,
2526
}
2627

2728
/// Target configuration
2829
#[derive(Debug, Deserialize, PartialEq, Eq)]
30+
#[serde(rename_all = "kebab-case")]
2931
pub struct CrossTargetConfig {
3032
xargo: Option<bool>,
33+
build_std: Option<bool>,
3134
image: Option<String>,
3235
runner: Option<String>,
3336
#[serde(default)]
@@ -79,6 +82,11 @@ impl CrossToml {
7982
self.get_bool(target, |b| b.xargo, |t| t.xargo)
8083
}
8184

85+
/// Returns the `build.build-std` or the `target.{}.build-std` part of `Cross.toml`
86+
pub fn build_std(&self, target: &Target) -> (Option<bool>, Option<bool>) {
87+
self.get_bool(target, |b| b.build_std, |t| t.build_std)
88+
}
89+
8290
/// Returns the list of environment variables to pass through for `build`,
8391
pub fn env_passthrough_build(&self) -> &[String] {
8492
&self.build.env.passthrough
@@ -165,6 +173,7 @@ mod tests {
165173
passthrough: vec!["VAR1".to_string(), "VAR2".to_string()],
166174
},
167175
xargo: Some(true),
176+
build_std: None,
168177
default_target: None,
169178
},
170179
};
@@ -198,6 +207,7 @@ mod tests {
198207
volumes: vec!["VOL1_ARG".to_string(), "VOL2_ARG".to_string()],
199208
},
200209
xargo: Some(false),
210+
build_std: Some(true),
201211
image: Some("test-image".to_string()),
202212
runner: None,
203213
},
@@ -214,6 +224,7 @@ mod tests {
214224
passthrough = ["VAR1", "VAR2"]
215225
[target.aarch64-unknown-linux-gnu]
216226
xargo = false
227+
build-std = true
217228
image = "test-image"
218229
"#;
219230
let (parsed_cfg, unused) = CrossToml::parse(test_str)?;

src/lib.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,10 +349,18 @@ pub fn run() -> Result<ExitStatus> {
349349
is_nightly = channel == Channel::Nightly;
350350
}
351351

352+
// build-std overrides xargo, but only use it if it's a built-in
353+
// tool but not an available target or doesn't have rust-std.
352354
let available_targets = rustup::available_targets(&toolchain, verbose)?;
353-
let uses_xargo = config
354-
.xargo(&target)
355-
.unwrap_or_else(|| !target.is_builtin() || !available_targets.contains(&target));
355+
let uses_build_std = config.build_std(&target).unwrap_or(false);
356+
let uses_xargo =
357+
!uses_build_std && config.xargo(&target).unwrap_or(!target.is_builtin());
358+
if !is_nightly && uses_build_std {
359+
eyre::bail!(
360+
"no rust-std component available for {}: must use nightly",
361+
target.triple()
362+
);
363+
}
356364

357365
if !uses_xargo
358366
&& !available_targets.is_installed(&target)
@@ -410,6 +418,9 @@ pub fn run() -> Result<ExitStatus> {
410418
if is_test && args.enable_doctests && is_nightly {
411419
filtered_args.push("-Zdoctest-xcompile".to_string());
412420
}
421+
if uses_build_std {
422+
filtered_args.push("-Zbuild-std".to_string());
423+
}
413424

414425
if target.needs_docker() && args.subcommand.map(|sc| sc.needs_docker()).unwrap_or(false)
415426
{

0 commit comments

Comments
 (0)