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

Resolve merge conflicts with #10330 #10386

61 changes: 40 additions & 21 deletions src/cargo/core/compiler/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ 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 std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet};
use std::env;
use std::path::PathBuf;
Expand Down Expand Up @@ -133,7 +134,8 @@ pub fn generate_std_roots(
crates: &[String],
std_resolve: &Resolve,
std_features: &ResolvedFeatures,
kinds: &[CompileKind],
requested_kinds: &[CompileKind],
explicit_host_kind: CompileKind,
package_set: &PackageSet<'_>,
interner: &UnitInterner,
profiles: &Profiles,
Expand All @@ -147,41 +149,58 @@ pub fn generate_std_roots(
let std_pkgs = package_set.get_many(std_ids)?;
// Generate a map of Units for each kind requested.
let mut ret = HashMap::new();
for pkg in std_pkgs {
let lib = pkg
.targets()
.iter()
.find(|t| t.is_lib())
.expect("std has a lib");
let unit_for = UnitFor::new_normal();
// I don't think we need to bother with Check here, the difference
// in time is minimal, and the difference in caching is
// significant.
let mode = CompileMode::Build;
let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);

for kind in kinds {
let list = ret.entry(*kind).or_insert_with(Vec::new);
let std_pkg_infos: Vec<_> = std_pkgs
.iter()
.map(|pkg| {
let lib = pkg
.targets()
.iter()
.find(|t| t.is_lib())
.expect("std has a lib");
let unit_for = UnitFor::new_normal();
let features =
std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);
(pkg, lib, unit_for, features)
})
.collect();

for kind in package_set
.packages()
.flat_map(|pkg| pkg.explicit_kinds(requested_kinds, explicit_host_kind))
{
let e = match ret.entry(kind) {
Entry::Vacant(e) => e,
Entry::Occupied(_) => continue,
};
let units = std_pkg_infos.iter().map(|(pkg, lib, unit_for, features)| {
// I don't think we need to bother with Check here, the difference
// in time is minimal, and the difference in caching is
// significant.
let mode = CompileMode::Build;
let profile = profiles.get_profile(
pkg.package_id(),
/*is_member*/ false,
/*is_local*/ false,
unit_for,
*unit_for,
mode,
*kind,
kind,
);
list.push(interner.intern(
interner.intern(
pkg,
lib,
profile,
*kind,
kind,
mode,
features.clone(),
/*is_std*/ true,
/*dep_hash*/ 0,
));
}
)
});

e.insert(units.collect());
}

Ok(ret)
}

Expand Down
28 changes: 28 additions & 0 deletions src/cargo/core/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,34 @@ impl Package {
self.targets().iter().any(|t| t.is_custom_build())
}

/// Returns explicit kinds either forced by `forced-target` in `Cargo.toml`,
/// fallback to `default-target`, or specified in cli parameters.
///
/// If `--target` has not been specified, then the return value
/// is the same as if `--target $HOST` was specified. See
/// `rebuild_unit_graph_shared` for why callers want to do this.
/// However, if the package has its own `package.default-target`
/// key, then that gets used instead of `$HOST`
pub fn explicit_kinds(
&self,
requested_kinds: &[CompileKind],
explicit_host_kind: CompileKind,
) -> Vec<CompileKind> {
if let Some(k) = self.manifest().forced_kind() {
vec![k]
} else {
requested_kinds
.iter()
.map(|kind| match kind {
CompileKind::Host => {
self.manifest().default_kind().unwrap_or(explicit_host_kind)
}
CompileKind::Target(t) => CompileKind::Target(*t),
})
.collect()
}
}

pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Package {
Package {
inner: Rc::new(PackageInner {
Expand Down
38 changes: 4 additions & 34 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,12 +404,7 @@ pub fn create_bcx<'a, 'cfg>(
.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");
}

let (std_package_set, std_resolve, std_features) =
standard_lib::resolve_std(ws, &target_data, &build_config.requested_kinds, crates)?;
pkg_set.add_set(std_package_set);
Expand Down Expand Up @@ -476,14 +471,6 @@ pub fn create_bcx<'a, 'cfg>(
// assuming `--target $HOST` was specified. See
// `rebuild_unit_graph_shared` for more on why this is done.
let explicit_host_kind = CompileKind::Target(CompileTarget::new(&target_data.rustc.host)?);
let explicit_host_kinds: Vec<_> = build_config
.requested_kinds
.iter()
.map(|kind| match kind {
CompileKind::Host => explicit_host_kind,
CompileKind::Target(t) => CompileKind::Target(*t),
})
.collect();

// Passing `build_config.requested_kinds` instead of
// `explicit_host_kinds` here so that `generate_targets` can do
Expand Down Expand Up @@ -562,7 +549,8 @@ pub fn create_bcx<'a, 'cfg>(
&crates,
std_resolve,
std_features,
&explicit_host_kinds,
&build_config.requested_kinds,
explicit_host_kind,
&pkg_set,
interner,
&profiles,
Expand Down Expand Up @@ -1059,25 +1047,7 @@ fn generate_targets(
let features_for = FeaturesFor::from_for_host(target.proc_macro());
let features = resolved_features.activated_features(pkg.package_id(), features_for);

// If `--target` has not been specified, then the unit
// graph is built almost like if `--target $HOST` was
// specified. See `rebuild_unit_graph_shared` for more on
// why this is done. However, if the package has its own
// `package.target` key, then this gets used instead of
// `$HOST`
let explicit_kinds = if let Some(k) = pkg.manifest().forced_kind() {
vec![k]
} else {
requested_kinds
.iter()
.map(|kind| match kind {
CompileKind::Host => {
pkg.manifest().default_kind().unwrap_or(explicit_host_kind)
}
CompileKind::Target(t) => CompileKind::Target(*t),
})
.collect()
};
let explicit_kinds = pkg.explicit_kinds(requested_kinds, explicit_host_kind);

for kind in explicit_kinds.iter() {
let profile = profiles.get_profile(
Expand Down
44 changes: 44 additions & 0 deletions tests/build-std/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,50 @@ fn cross_custom() {
.run();
}

/// like cross-custom but uses per-package-target instead
#[cargo_test(build_std)]
fn per_package_target() {
let p = project()
.file(
"Cargo.toml",
r#"
cargo-features = ["per-package-target"]
[package]
name = "foo"
version = "0.1.0"
edition = "2018"
default-target = "custom-target.json"

[target.custom-target.dependencies]
dep = { path = "dep" }
"#,
)
.file(
"src/lib.rs",
"#![no_std] pub fn f() -> u32 { dep::answer() }",
)
.file("dep/Cargo.toml", &basic_manifest("dep", "0.1.0"))
.file("dep/src/lib.rs", "#![no_std] pub fn answer() -> u32 { 42 }")
.file(
"custom-target.json",
r#"
{
"llvm-target": "x86_64-unknown-none-gnu",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"linker-flavor": "ld.lld"
}
"#,
)
.build();

p.cargo("build -v").build_std_arg("core").run();
}

#[cargo_test(build_std)]
fn custom_test_framework() {
let p = project()
Expand Down