Skip to content

Add support for -Zbuild-std to cargo fetch #10129

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

Merged
merged 1 commit into from
May 4, 2022
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
5 changes: 5 additions & 0 deletions src/cargo/core/compiler/build_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ impl BuildConfig {
anyhow::bail!("jobs may not be 0");
}

if config.cli_unstable().build_std.is_some() && requested_kinds[0].is_host() {
// TODO: This should eventually be fixed.
anyhow::bail!("-Zbuild-std requires --target");
}

Ok(BuildConfig {
requested_kinds,
jobs,
Expand Down
39 changes: 37 additions & 2 deletions src/cargo/core/compiler/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ use crate::core::resolver::HasDevUnits;
use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace};
use crate::ops::{self, Packages};
use crate::util::errors::CargoResult;
use crate::Config;
use std::collections::{HashMap, HashSet};
use std::env;
use std::path::PathBuf;

use super::BuildConfig;

/// Parse the `-Zbuild-std` flag.
pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
// This is a temporary hack until there is a more principled way to
Expand All @@ -31,13 +34,45 @@ pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
crates.into_iter().map(|s| s.to_string()).collect()
}

pub(crate) fn std_crates(config: &Config, units: Option<&[Unit]>) -> Option<Vec<String>> {
let crates = config.cli_unstable().build_std.as_ref()?.clone();

// Only build libtest if it looks like it is needed.
let mut crates = crates.clone();
// If we know what units we're building, we can filter for libtest depending on the jobs.
if let Some(units) = units {
if units
.iter()
.any(|unit| unit.mode.is_rustc_test() && unit.target.harness())
{
// Only build libtest when libstd is built (libtest depends on libstd)
if crates.iter().any(|c| c == "std") && !crates.iter().any(|c| c == "test") {
crates.push("test".to_string());
}
}
} else {
// We don't know what jobs are going to be run, so download libtest just in case.
if !crates.iter().any(|c| c == "test") {
crates.push("test".to_string())
}
}

Some(crates)
}

/// Resolve the standard library dependencies.
pub fn resolve_std<'cfg>(
ws: &Workspace<'cfg>,
target_data: &RustcTargetData<'cfg>,
requested_targets: &[CompileKind],
build_config: &BuildConfig,
crates: &[String],
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {
if build_config.build_plan {
ws.config()
.shell()
.warn("-Zbuild-std does not currently fully support --build-plan")?;
}

let src_path = detect_sysroot_src_path(target_data)?;
let to_patch = [
"rustc-std-workspace-core",
Expand Down Expand Up @@ -114,7 +149,7 @@ pub fn resolve_std<'cfg>(
let resolve = ops::resolve_ws_with_opts(
&std_ws,
target_data,
requested_targets,
&build_config.requested_kinds,
&cli_features,
&specs,
HasDevUnits::No,
Expand Down
27 changes: 2 additions & 25 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,19 +401,8 @@ pub fn create_bcx<'a, 'cfg>(
} = resolve;

let std_resolve_features = if let Some(crates) = &config.cli_unstable().build_std {
if build_config.build_plan {
config
.shell()
.warn("-Zbuild-std does not currently fully support --build-plan")?;
}
if build_config.requested_kinds[0].is_host() {
// TODO: This should eventually be fixed. Unfortunately it is not
// easy to get the host triple in BuildConfig. Consider changing
// requested_target to an enum, or some other approach.
anyhow::bail!("-Zbuild-std requires --target");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't delete this, it's here for a reason. The -Zbuild-std unit graph is not correct unless --target is passed and a lot more is needed to get this working without it. Simply because the test suite doesn't fail doesn't mean this can be deleted.

let (std_package_set, std_resolve, std_features) =
standard_lib::resolve_std(ws, &target_data, &build_config.requested_kinds, crates)?;
standard_lib::resolve_std(ws, &target_data, &build_config, crates)?;
pkg_set.add_set(std_package_set);
Some((std_resolve, std_features))
} else {
Expand Down Expand Up @@ -554,19 +543,7 @@ pub fn create_bcx<'a, 'cfg>(
None => Vec::new(),
};

let std_roots = if let Some(crates) = &config.cli_unstable().build_std {
// Only build libtest if it looks like it is needed.
let mut crates = crates.clone();
if !crates.iter().any(|c| c == "test")
&& units
.iter()
.any(|unit| unit.mode.is_rustc_test() && unit.target.harness())
{
// Only build libtest when libstd is built (libtest depends on libstd)
if crates.iter().any(|c| c == "std") {
crates.push("test".to_string());
}
}
let std_roots = if let Some(crates) = standard_lib::std_crates(config, Some(&units)) {
let (std_resolve, std_features) = std_resolve_features.as_ref().unwrap();
standard_lib::generate_std_roots(
&crates,
Expand Down
11 changes: 10 additions & 1 deletion src/cargo/ops/cargo_fetch.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::core::compiler::standard_lib;
use crate::core::compiler::{BuildConfig, CompileMode, RustcTargetData};
use crate::core::{PackageSet, Resolve, Workspace};
use crate::ops;
Expand All @@ -17,7 +18,7 @@ pub fn fetch<'a>(
options: &FetchOptions<'a>,
) -> CargoResult<(Resolve, PackageSet<'a>)> {
ws.emit_warnings()?;
let (packages, resolve) = ops::resolve_ws(ws)?;
let (mut packages, resolve) = ops::resolve_ws(ws)?;

let jobs = Some(1);
let keep_going = false;
Expand Down Expand Up @@ -64,6 +65,14 @@ pub fn fetch<'a>(
.map(|(id, _deps)| id);
deps_to_fetch.extend(deps);
}

// If -Zbuild-std was passed, download dependencies for the standard library.
// We don't know ahead of time what jobs we'll be running, so tell `std_crates` that.
if let Some(crates) = standard_lib::std_crates(config, None) {
let (std_package_set, _, _) = standard_lib::resolve_std(ws, &data, &build_config, &crates)?;
packages.add_set(std_package_set);
}

packages.get_many(to_download)?;

Ok((resolve, packages))
Expand Down
19 changes: 19 additions & 0 deletions tests/testsuite/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,3 +690,22 @@ fn proc_macro_only() {
.with_stderr_contains("[FINISHED] [..]")
.run();
}

#[cargo_test]
fn fetch() {
let setup = match setup() {
Some(s) => s,
None => return,
};
let p = project().file("src/main.rs", "fn main() {}").build();
p.cargo("fetch")
.build_std(&setup)
.target_host()
.with_stderr_contains("[DOWNLOADED] [..]")
.run();
p.cargo("build")
.build_std(&setup)
.target_host()
.with_stderr_does_not_contain("[DOWNLOADED] [..]")
.run();
}