Skip to content

Commit a44758a

Browse files
committed
Auto merge of #10129 - jyn514:fetch-build-std, r=weihanglo
Add support for `-Zbuild-std` to `cargo fetch` This allows downloading the dependencies for libstd in advance, which can be useful in e.g. sandboxed build environments. Fixes rust-lang/wg-cargo-std-aware#22. r? `@ehuss`
2 parents ad05cec + 55b680c commit a44758a

File tree

5 files changed

+73
-28
lines changed

5 files changed

+73
-28
lines changed

src/cargo/core/compiler/build_config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ impl BuildConfig {
8484
anyhow::bail!("jobs may not be 0");
8585
}
8686

87+
if config.cli_unstable().build_std.is_some() && requested_kinds[0].is_host() {
88+
// TODO: This should eventually be fixed.
89+
anyhow::bail!("-Zbuild-std requires --target");
90+
}
91+
8792
Ok(BuildConfig {
8893
requested_kinds,
8994
jobs,

src/cargo/core/compiler/standard_lib.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ use crate::core::resolver::HasDevUnits;
99
use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace};
1010
use crate::ops::{self, Packages};
1111
use crate::util::errors::CargoResult;
12+
use crate::Config;
1213
use std::collections::{HashMap, HashSet};
1314
use std::env;
1415
use std::path::PathBuf;
1516

17+
use super::BuildConfig;
18+
1619
/// Parse the `-Zbuild-std` flag.
1720
pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
1821
// This is a temporary hack until there is a more principled way to
@@ -31,13 +34,45 @@ pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
3134
crates.into_iter().map(|s| s.to_string()).collect()
3235
}
3336

37+
pub(crate) fn std_crates(config: &Config, units: Option<&[Unit]>) -> Option<Vec<String>> {
38+
let crates = config.cli_unstable().build_std.as_ref()?.clone();
39+
40+
// Only build libtest if it looks like it is needed.
41+
let mut crates = crates.clone();
42+
// If we know what units we're building, we can filter for libtest depending on the jobs.
43+
if let Some(units) = units {
44+
if units
45+
.iter()
46+
.any(|unit| unit.mode.is_rustc_test() && unit.target.harness())
47+
{
48+
// Only build libtest when libstd is built (libtest depends on libstd)
49+
if crates.iter().any(|c| c == "std") && !crates.iter().any(|c| c == "test") {
50+
crates.push("test".to_string());
51+
}
52+
}
53+
} else {
54+
// We don't know what jobs are going to be run, so download libtest just in case.
55+
if !crates.iter().any(|c| c == "test") {
56+
crates.push("test".to_string())
57+
}
58+
}
59+
60+
Some(crates)
61+
}
62+
3463
/// Resolve the standard library dependencies.
3564
pub fn resolve_std<'cfg>(
3665
ws: &Workspace<'cfg>,
3766
target_data: &RustcTargetData<'cfg>,
38-
requested_targets: &[CompileKind],
67+
build_config: &BuildConfig,
3968
crates: &[String],
4069
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {
70+
if build_config.build_plan {
71+
ws.config()
72+
.shell()
73+
.warn("-Zbuild-std does not currently fully support --build-plan")?;
74+
}
75+
4176
let src_path = detect_sysroot_src_path(target_data)?;
4277
let to_patch = [
4378
"rustc-std-workspace-core",
@@ -114,7 +149,7 @@ pub fn resolve_std<'cfg>(
114149
let resolve = ops::resolve_ws_with_opts(
115150
&std_ws,
116151
target_data,
117-
requested_targets,
152+
&build_config.requested_kinds,
118153
&cli_features,
119154
&specs,
120155
HasDevUnits::No,

src/cargo/ops/cargo_compile.rs

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -401,19 +401,8 @@ pub fn create_bcx<'a, 'cfg>(
401401
} = resolve;
402402

403403
let std_resolve_features = if let Some(crates) = &config.cli_unstable().build_std {
404-
if build_config.build_plan {
405-
config
406-
.shell()
407-
.warn("-Zbuild-std does not currently fully support --build-plan")?;
408-
}
409-
if build_config.requested_kinds[0].is_host() {
410-
// TODO: This should eventually be fixed. Unfortunately it is not
411-
// easy to get the host triple in BuildConfig. Consider changing
412-
// requested_target to an enum, or some other approach.
413-
anyhow::bail!("-Zbuild-std requires --target");
414-
}
415404
let (std_package_set, std_resolve, std_features) =
416-
standard_lib::resolve_std(ws, &target_data, &build_config.requested_kinds, crates)?;
405+
standard_lib::resolve_std(ws, &target_data, &build_config, crates)?;
417406
pkg_set.add_set(std_package_set);
418407
Some((std_resolve, std_features))
419408
} else {
@@ -554,19 +543,7 @@ pub fn create_bcx<'a, 'cfg>(
554543
None => Vec::new(),
555544
};
556545

557-
let std_roots = if let Some(crates) = &config.cli_unstable().build_std {
558-
// Only build libtest if it looks like it is needed.
559-
let mut crates = crates.clone();
560-
if !crates.iter().any(|c| c == "test")
561-
&& units
562-
.iter()
563-
.any(|unit| unit.mode.is_rustc_test() && unit.target.harness())
564-
{
565-
// Only build libtest when libstd is built (libtest depends on libstd)
566-
if crates.iter().any(|c| c == "std") {
567-
crates.push("test".to_string());
568-
}
569-
}
546+
let std_roots = if let Some(crates) = standard_lib::std_crates(config, Some(&units)) {
570547
let (std_resolve, std_features) = std_resolve_features.as_ref().unwrap();
571548
standard_lib::generate_std_roots(
572549
&crates,

src/cargo/ops/cargo_fetch.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::core::compiler::standard_lib;
12
use crate::core::compiler::{BuildConfig, CompileMode, RustcTargetData};
23
use crate::core::{PackageSet, Resolve, Workspace};
34
use crate::ops;
@@ -17,7 +18,7 @@ pub fn fetch<'a>(
1718
options: &FetchOptions<'a>,
1819
) -> CargoResult<(Resolve, PackageSet<'a>)> {
1920
ws.emit_warnings()?;
20-
let (packages, resolve) = ops::resolve_ws(ws)?;
21+
let (mut packages, resolve) = ops::resolve_ws(ws)?;
2122

2223
let jobs = Some(1);
2324
let keep_going = false;
@@ -64,6 +65,14 @@ pub fn fetch<'a>(
6465
.map(|(id, _deps)| id);
6566
deps_to_fetch.extend(deps);
6667
}
68+
69+
// If -Zbuild-std was passed, download dependencies for the standard library.
70+
// We don't know ahead of time what jobs we'll be running, so tell `std_crates` that.
71+
if let Some(crates) = standard_lib::std_crates(config, None) {
72+
let (std_package_set, _, _) = standard_lib::resolve_std(ws, &data, &build_config, &crates)?;
73+
packages.add_set(std_package_set);
74+
}
75+
6776
packages.get_many(to_download)?;
6877

6978
Ok((resolve, packages))

tests/testsuite/standard_lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,3 +690,22 @@ fn proc_macro_only() {
690690
.with_stderr_contains("[FINISHED] [..]")
691691
.run();
692692
}
693+
694+
#[cargo_test]
695+
fn fetch() {
696+
let setup = match setup() {
697+
Some(s) => s,
698+
None => return,
699+
};
700+
let p = project().file("src/main.rs", "fn main() {}").build();
701+
p.cargo("fetch")
702+
.build_std(&setup)
703+
.target_host()
704+
.with_stderr_contains("[DOWNLOADED] [..]")
705+
.run();
706+
p.cargo("build")
707+
.build_std(&setup)
708+
.target_host()
709+
.with_stderr_does_not_contain("[DOWNLOADED] [..]")
710+
.run();
711+
}

0 commit comments

Comments
 (0)