cargo-metadata: support -Zbindeps info

This commit is contained in:
Weihang Lo 2023-01-06 17:00:55 +00:00
parent ca626c5915
commit e5ec492b6f
No known key found for this signature in database
GPG Key ID: D7DBF189825E82E7
4 changed files with 213 additions and 23 deletions

View File

@ -1,8 +1,8 @@
use crate::core::compiler::{CompileKind, RustcTargetData};
use crate::core::dependency::DepKind;
use crate::core::dependency::{ArtifactKind, DepKind};
use crate::core::package::SerializedPackage;
use crate::core::resolver::{features::CliFeatures, HasDevUnits, Resolve};
use crate::core::{Dependency, Package, PackageId, Workspace};
use crate::core::{Package, PackageId, Target, Workspace};
use crate::ops::{self, Packages};
use crate::util::interning::InternedString;
use crate::util::CargoResult;
@ -90,15 +90,26 @@ struct Dep {
struct DepKindInfo {
kind: DepKind,
target: Option<Platform>,
}
impl From<&Dependency> for DepKindInfo {
fn from(dep: &Dependency) -> DepKindInfo {
DepKindInfo {
kind: dep.kind(),
target: dep.platform().cloned(),
}
}
// vvvvv The fields below are introduced for `-Z bindeps`.
/// Artifact's crate type, e.g. staticlib, cdylib, bin...
#[serde(skip_serializing_if = "Option::is_none")]
artifact: Option<&'static str>,
/// What the manifest calls the crate.
///
/// A renamed dependency will show the rename instead of original name.
#[serde(skip_serializing_if = "Option::is_none")]
extern_name: Option<InternedString>,
/// Equivalent to `{ target = "…" }` in an artifact dependency requirement.
///
/// * If the target points to a custom target JSON file, the path will be absolute.
/// * If the target is a build assumed target `{ target = "target" }`, it will show as `<target>`.
#[serde(skip_serializing_if = "Option::is_none")]
compile_target: Option<InternedString>,
/// Executable name for an artifact binary dependency.
#[serde(skip_serializing_if = "Option::is_none")]
bin_name: Option<String>,
// ^^^^^ The fields above are introduced for `-Z bindeps`.
}
/// Builds the resolve graph as it will be displayed to the user.
@ -206,22 +217,101 @@ fn build_resolve_graph_r(
}
})
.filter_map(|(dep_id, deps)| {
let mut dep_kinds: Vec<_> = deps.iter().map(DepKindInfo::from).collect();
let mut dep_kinds = Vec::new();
let targets = package_map[&dep_id].targets();
// Try to get the extern name for lib, or crate name for bins.
let extern_name = |target| {
resolve
.extern_crate_name_and_dep_name(pkg_id, dep_id, target)
.map(|(ext_crate_name, _)| ext_crate_name)
.ok()
};
let lib_target_name = targets.iter().find(|t| t.is_lib()).map(extern_name);
for dep in deps.iter() {
let mut include_lib = || {
dep_kinds.push(DepKindInfo {
kind: dep.kind(),
target: dep.platform().cloned(),
artifact: None,
extern_name: lib_target_name,
compile_target: None,
bin_name: None,
});
};
// When we do have a library target, include them in deps if...
match (dep.artifact(), lib_target_name) {
// it is also an artifact dep with `{ …, lib = true }`
(Some(a), Some(_)) if a.is_lib() => include_lib(),
// it is not an artifact dep at all
(None, Some(_)) => include_lib(),
_ => {}
}
// No need to proceed if there is no artifact dependency.
let Some(artifact_requirements) = dep.artifact() else {
continue;
};
let compile_target = match artifact_requirements.target() {
Some(t) => t
.to_compile_target()
.map(|t| t.rustc_target())
// Given that Cargo doesn't know which target it should resolve to,
// when an artifact dep is specified with { target = "target" },
// keep it with a special "<target>" string,
.or_else(|| Some(InternedString::new("<target>"))),
None => None,
};
let mut extend = |kind: &ArtifactKind, filter: &dyn Fn(&&Target) -> bool| {
let iter = targets.iter().filter(filter).map(|target| DepKindInfo {
kind: dep.kind(),
target: dep.platform().cloned(),
artifact: Some(kind.crate_type()),
extern_name: extern_name(target),
compile_target,
bin_name: target.is_bin().then(|| target.name().to_string()),
});
dep_kinds.extend(iter);
};
for kind in artifact_requirements.kinds() {
match kind {
ArtifactKind::Cdylib => extend(kind, &|t| t.is_cdylib()),
ArtifactKind::Staticlib => extend(kind, &|t| t.is_staticlib()),
ArtifactKind::AllBinaries => extend(kind, &|t| t.is_bin()),
ArtifactKind::SelectedBinary(bin_name) => {
extend(kind, &|t| t.is_bin() && t.name() == bin_name.as_str())
}
};
}
}
dep_kinds.sort();
package_map
.get(&dep_id)
.and_then(|pkg| pkg.targets().iter().find(|t| t.is_lib()))
.and_then(|lib_target| {
resolve
.extern_crate_name_and_dep_name(pkg_id, dep_id, lib_target)
.map(|(ext_crate_name, _)| ext_crate_name)
.ok()
})
.map(|name| Dep {
let pkg = normalize_id(dep_id);
match (lib_target_name, dep_kinds.len()) {
(Some(name), _) => Some(Dep {
name,
pkg: normalize_id(dep_id),
pkg,
dep_kinds,
})
}),
// No lib target exists but contains artifact deps.
(None, 1..) => Some(Dep {
name: InternedString::new(""),
pkg,
dep_kinds,
}),
// No lib or artifact dep exists.
// Ususally this mean parent depending on non-lib bin crate.
(None, _) => None,
}
})
.collect();
let dumb_deps: Vec<PackageId> = deps.iter().map(|dep| normalize_id(dep.pkg)).collect();

View File

@ -3393,6 +3393,7 @@ fn metadata_master_consistency() {
"pkg": "bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)",
"dep_kinds": [
{
"extern_name": "bar",
"kind": null,
"target": null
}

View File

@ -526,6 +526,7 @@ fn cargo_metadata_with_deps_and_version() {
{
"dep_kinds": [
{
"extern_name": "baz",
"kind": null,
"target": null
}
@ -552,6 +553,7 @@ fn cargo_metadata_with_deps_and_version() {
{
"dep_kinds": [
{
"extern_name": "bar",
"kind": null,
"target": null
}
@ -562,6 +564,7 @@ fn cargo_metadata_with_deps_and_version() {
{
"dep_kinds": [
{
"extern_name": "foobar",
"kind": "dev",
"target": null
}
@ -1617,20 +1620,57 @@ fn workspace_metadata_with_dependencies_and_resolve() {
{
"dependencies": [
"artifact 0.5.0 (path+file://[..]/foo/artifact)",
"bin-only-artifact 0.5.0 (path+file://[..]/foo/bin-only-artifact)",
"non-artifact 0.5.0 (path+file://[..]/foo/non-artifact)"
],
"deps": [
{
"dep_kinds": [
{
"extern_name": "artifact",
"kind": null,
"target": null
},
{
"artifact": "bin",
"bin_name": "baz-name",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "baz_name",
"kind": null,
"target": null
},
{
"artifact": "cdylib",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "artifact",
"kind": null,
"target": null
},
{
"artifact": "staticlib",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "artifact",
"kind": null,
"target": null
},
{
"extern_name": "artifact",
"kind": "dev",
"target": null
},
{
"artifact": "bin",
"bin_name": "bar-name",
"compile_target": "<target>",
"extern_name": "bar_name",
"kind": "build",
"target": null
},
{
"artifact": "bin",
"bin_name": "baz-name",
"compile_target": "<target>",
"extern_name": "baz_name",
"kind": "build",
"target": null
}
@ -1641,14 +1681,53 @@ fn workspace_metadata_with_dependencies_and_resolve() {
{
"dep_kinds": [
{
"artifact": "bin",
"bin_name": "a-name",
"extern_name": "a_name",
"kind": null,
"target": null
},
{
"artifact": "bin",
"bin_name": "b-name",
"extern_name": "b_name",
"kind": "dev",
"target": null
},
{
"artifact": "bin",
"bin_name": "a-name",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "a_name",
"kind": "build",
"target": null
},
{
"artifact": "bin",
"bin_name": "b-name",
"compile_target": "wasm32-unknown-unknown",
"extern_name": "b_name",
"kind": "build",
"target": null
}
],
"name": "",
"pkg": "bin-only-artifact 0.5.0 (path+file://[..]/foo/bin-only-artifact)"
},
{
"dep_kinds": [
{
"extern_name": "non_artifact",
"kind": null,
"target": null
},
{
"extern_name": "non_artifact",
"kind": "dev",
"target": null
},
{
"extern_name": "non_artifact",
"kind": "build",
"target": null
}
@ -2625,6 +2704,7 @@ fn rename_dependency() {
{
"dep_kinds": [
{
"extern_name": "bar",
"kind": null,
"target": null
}
@ -2635,6 +2715,7 @@ fn rename_dependency() {
{
"dep_kinds": [
{
"extern_name": "baz",
"kind": null,
"target": null
}
@ -3251,6 +3332,7 @@ fn filter_platform() {
"pkg": "alt-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "alt_dep",
"kind": null,
"target": "$ALT_TRIPLE"
}
@ -3261,6 +3343,7 @@ fn filter_platform() {
"pkg": "cfg-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "cfg_dep",
"kind": null,
"target": "cfg(foobar)"
}
@ -3271,6 +3354,7 @@ fn filter_platform() {
"pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "host_dep",
"kind": null,
"target": "$HOST_TRIPLE"
}
@ -3281,6 +3365,7 @@ fn filter_platform() {
"pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "normal_dep",
"kind": null,
"target": null
}
@ -3362,6 +3447,7 @@ fn filter_platform() {
"pkg": "alt-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "alt_dep",
"kind": null,
"target": "$ALT_TRIPLE"
}
@ -3372,6 +3458,7 @@ fn filter_platform() {
"pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "normal_dep",
"kind": null,
"target": null
}
@ -3437,6 +3524,7 @@ fn filter_platform() {
"pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "host_dep",
"kind": null,
"target": "$HOST_TRIPLE"
}
@ -3447,6 +3535,7 @@ fn filter_platform() {
"pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "normal_dep",
"kind": null,
"target": null
}
@ -3528,6 +3617,7 @@ fn filter_platform() {
"pkg": "cfg-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "cfg_dep",
"kind": null,
"target": "cfg(foobar)"
}
@ -3538,6 +3628,7 @@ fn filter_platform() {
"pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "host_dep",
"kind": null,
"target": "$HOST_TRIPLE"
}
@ -3548,6 +3639,7 @@ fn filter_platform() {
"pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dep_kinds": [
{
"extern_name": "normal_dep",
"kind": null,
"target": null
}
@ -3645,14 +3737,17 @@ fn dep_kinds() {
"pkg": "bar 0.1.0 [..]",
"dep_kinds": [
{
"extern_name": "bar",
"kind": null,
"target": null
},
{
"extern_name": "bar",
"kind": "dev",
"target": null
},
{
"extern_name": "bar",
"kind": "build",
"target": null
}
@ -3663,6 +3758,7 @@ fn dep_kinds() {
"pkg": "winapi 0.1.0 [..]",
"dep_kinds": [
{
"extern_name": "winapi",
"kind": null,
"target": "cfg(windows)"
}
@ -3753,6 +3849,7 @@ fn dep_kinds_workspace() {
"pkg": "foo 0.1.0 (path+file://[..]/foo)",
"dep_kinds": [
{
"extern_name": "foo",
"kind": null,
"target": null
}
@ -3778,6 +3875,7 @@ fn dep_kinds_workspace() {
"pkg": "dep 0.5.0 (path+file://[..]/foo/dep)",
"dep_kinds": [
{
"extern_name": "dep",
"kind": null,
"target": null
}

View File

@ -608,6 +608,7 @@ fn update_precise_first_run() {
{
"dep_kinds": [
{
"extern_name": "serde",
"kind": null,
"target": null
}