diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index e0f0e5f96cf..917a844f353 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -622,7 +622,7 @@ impl<'gctx> PackageSet<'gctx> { root_ids: &[PackageId], has_dev_units: HasDevUnits, requested_kinds: &[CompileKind], - target_data: &RustcTargetData<'gctx>, + target_data: &mut RustcTargetData<'gctx>, force_all_targets: ForceAllTargets, ) -> CargoResult<()> { fn collect_used_deps( @@ -631,7 +631,7 @@ impl<'gctx> PackageSet<'gctx> { pkg_id: PackageId, has_dev_units: HasDevUnits, requested_kind: CompileKind, - target_data: &RustcTargetData<'_>, + target_data: &mut RustcTargetData<'_>, force_all_targets: ForceAllTargets, ) -> CargoResult<()> { if !used.insert((pkg_id, requested_kind)) { @@ -645,29 +645,45 @@ impl<'gctx> PackageSet<'gctx> { requested_kinds, target_data, force_all_targets, - ); - for (pkg_id, deps) in filtered_deps { + ) + .map(|(dep_pkg_id, deps)| { + let artifact_kinds = deps + .iter() + .filter_map(|dep| { + Some(( + dep.artifact()? + .target()? + .to_resolved_compile_kind(requested_kind), + dep.name_in_toml(), + )) + }) + .collect::>(); + (dep_pkg_id, artifact_kinds) + }) + .collect::>(); + for (dep_pkg_id, deps) in filtered_deps { collect_used_deps( used, resolve, - pkg_id, + dep_pkg_id, has_dev_units, requested_kind, target_data, force_all_targets, )?; - let artifact_kinds = deps.iter().filter_map(|dep| { - Some( - dep.artifact()? - .target()? - .to_resolved_compile_kind(*requested_kinds.iter().next().unwrap()), - ) - }); - for artifact_kind in artifact_kinds { + for (artifact_kind, dep_name) in deps { + let target_name = target_data.short_name(&artifact_kind).to_owned(); + target_data.merge_compile_kind(artifact_kind).with_context(|| { + format!( + "failed to determine target information for target `{target_name}`.\n \ + Artifact dependency `{dep_name}` in package `{pkg_id}` requires \ + building for `{target_name}`" + ) + })?; collect_used_deps( used, resolve, - pkg_id, + dep_pkg_id, has_dev_units, artifact_kind, target_data, @@ -678,6 +694,14 @@ impl<'gctx> PackageSet<'gctx> { Ok(()) } + let default_kinds; + let requested_kinds = if requested_kinds.is_empty() { + default_kinds = [CompileKind::Host]; + &default_kinds + } else { + requested_kinds + }; + // This is sorted by PackageId to get consistent behavior and error // messages for Cargo's testsuite. Perhaps there is a better ordering // that optimizes download time? diff --git a/tests/testsuite/artifact_dep.rs b/tests/testsuite/artifact_dep.rs index db28f921e59..622fca2a692 100644 --- a/tests/testsuite/artifact_dep.rs +++ b/tests/testsuite/artifact_dep.rs @@ -9,7 +9,7 @@ use cargo_test_support::compare::assert_e2e; use cargo_test_support::registry::{Package, RegistryBuilder}; use cargo_test_support::str; use cargo_test_support::{ - Project, basic_bin_manifest, basic_manifest, cross_compile, project, publish, registry, + Project, basic_bin_manifest, basic_manifest, cross_compile, git, project, publish, registry, rustc_host, }; @@ -3318,6 +3318,87 @@ Caused by: .run(); } +#[cargo_test] +fn transitive_build_script_artifact_dependency_with_valid_target_does_not_panic() { + if cross_compile_disabled() { + return; + } + let target = cross_compile::alternate(); + let fdb = git::new("fdb", |project| { + project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "fdb" + version = "0.0.0" + edition = "2015" + build = "build.rs" + + [dependencies] + redux_helper32 = {{ path = "redux_helper32/" }} + + [build-dependencies] + redux_helper32 = {{ path = "redux_helper32/", artifact = "bin", target = "{target}" }} + "#, + ), + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#"fn main() { + let bin = std::env::var_os("CARGO_BIN_FILE_REDUX_HELPER32").unwrap(); + assert!(std::path::PathBuf::from(bin).exists()); + }"#, + ) + .file( + "redux_helper32/Cargo.toml", + r#" + [package] + name = "redux_helper32" + version = "0.0.0" + edition = "2015" + "#, + ) + .file("redux_helper32/src/lib.rs", "") + .file("redux_helper32/src/main.rs", "fn main() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [dependencies] + fdb = {{ git = '{}' }} + "#, + fdb.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/fdb` +[LOCKING] 2 packages to latest compatible versions +[COMPILING] redux_helper32 v0.0.0 ([ROOTURL]/fdb#[..]) +[COMPILING] fdb v0.0.0 ([ROOTURL]/fdb#[..]) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_status(0) + .run(); +} + #[cargo_test] fn build_only_specified_artifact_library() { // Create a project with: