diff --git a/src/cargo/core/compiler/unit_dependencies.rs b/src/cargo/core/compiler/unit_dependencies.rs index 69ac801ff51..28a47b0dee8 100644 --- a/src/cargo/core/compiler/unit_dependencies.rs +++ b/src/cargo/core/compiler/unit_dependencies.rs @@ -1103,7 +1103,10 @@ impl<'a, 'cfg> State<'a, 'cfg> { // If this is an optional dependency, and the new feature resolver // did not enable it, don't include it. if dep.is_optional() { - let features_for = unit_for.map_to_features_for(dep.artifact()); + // This `unit_for` is from parent dep and *SHOULD* contains its own + // artifact dep infomration inside `artifact_target_for_features`. + // So, no need to map any artifact info from an incorrect `dep.artifact()`. + let features_for = unit_for.map_to_features_for(IS_NO_ARTIFACT_DEP); if !self.is_dep_activated(pkg_id, features_for, dep.name_in_toml()) { return false; } diff --git a/src/cargo/core/resolver/features.rs b/src/cargo/core/resolver/features.rs index a2dba2869cf..e2f2bd5c50c 100644 --- a/src/cargo/core/resolver/features.rs +++ b/src/cargo/core/resolver/features.rs @@ -853,12 +853,14 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> { ArtifactTarget::BuildDependencyAssumeTarget => self .requested_targets .iter() - .filter_map(|kind| match kind { - CompileKind::Host => None, - CompileKind::Target(target) => { - Some(FeaturesFor::ArtifactDep(*target)) + .map(|kind| match kind { + CompileKind::Host => { + let host_triple = self.target_data.rustc.host; + CompileTarget::new(&host_triple).unwrap() } + CompileKind::Target(target) => *target, }) + .map(FeaturesFor::ArtifactDep) .collect(), }), ) diff --git a/tests/testsuite/artifact_dep.rs b/tests/testsuite/artifact_dep.rs index 0665df649fd..0a39af05b23 100644 --- a/tests/testsuite/artifact_dep.rs +++ b/tests/testsuite/artifact_dep.rs @@ -2342,3 +2342,108 @@ fn calc_bin_artifact_fingerprint() { ) .run(); } + +#[cargo_test] +fn with_target_and_optional() { + // See rust-lang/cargo#10526 + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + &r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + [dependencies] + d1 = { path = "d1", artifact = "bin", optional = true, target = "$TARGET" } + "# + .replace("$TARGET", target), + ) + .file( + "src/main.rs", + r#" + fn main() { + let _b = include_bytes!(env!("CARGO_BIN_FILE_D1")); + } + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2021" + "#, + ) + .file("d1/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -Z bindeps -F d1 -v") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr( + "\ +[COMPILING] d1 v0.0.1 [..] +[RUNNING] `rustc --crate-name d1 [..]--crate-type bin[..] +[CHECKING] foo v0.0.1 [..] +[RUNNING] `rustc --crate-name foo [..]--cfg[..]d1[..] +[FINISHED] dev [..] +", + ) + .run(); +} + +#[cargo_test] +fn with_assumed_host_target_and_optional_build_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + [build-dependencies] + d1 = { path = "d1", artifact = "bin", optional = true, target = "target" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + std::env::var("CARGO_BIN_FILE_D1").unwrap(); + } + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2021" + "#, + ) + .file("d1/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -Z bindeps -F d1 -v") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_unordered( + "\ +[COMPILING] foo v0.0.1 ([CWD]) +[COMPILING] d1 v0.0.1 ([CWD]/d1) +[RUNNING] `rustc --crate-name build_script_build [..]--crate-type bin[..] +[RUNNING] `rustc --crate-name d1 [..]--crate-type bin[..] +[RUNNING] `[CWD]/target/debug/build/foo-[..]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]--cfg[..]d1[..] +[FINISHED] dev [..] +", + ) + .run(); +}