diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index a6b64a69260..0de0e8bd052 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -1,9 +1,9 @@ use crate::core::compiler::{CompileKind, CompileTarget, TargetInfo}; use crate::core::resolver::{Resolve, ResolveOpts}; -use crate::core::{Package, PackageId, Workspace}; +use crate::core::{dependency, Dependency, Package, PackageId, Workspace}; use crate::ops::{self, Packages}; use crate::util::CargoResult; - +use cargo_platform::Platform; use serde::Serialize; use std::collections::HashMap; use std::path::PathBuf; @@ -85,6 +85,22 @@ struct MetadataResolveNode { struct Dep { name: String, pkg: PackageId, + dep_kinds: Vec, +} + +#[derive(Serialize)] +struct DepKindInfo { + kind: dependency::Kind, + target: Option, +} + +impl From<&Dependency> for DepKindInfo { + fn from(dep: &Dependency) -> DepKindInfo { + DepKindInfo { + kind: dep.kind(), + target: dep.platform().cloned(), + } + } } /// Builds the resolve graph as it will be displayed to the user. @@ -167,12 +183,16 @@ fn build_resolve_graph_r( }), None => true, }) - .filter_map(|(dep_id, _deps)| { + .filter_map(|(dep_id, deps)| { package_map .get(&dep_id) .and_then(|pkg| pkg.targets().iter().find(|t| t.is_lib())) .and_then(|lib_target| resolve.extern_crate_name(pkg_id, dep_id, lib_target).ok()) - .map(|name| Dep { name, pkg: dep_id }) + .map(|name| Dep { + name, + pkg: dep_id, + dep_kinds: deps.iter().map(DepKindInfo::from).collect(), + }) }) .collect(); let dumb_deps: Vec = deps.iter().map(|dep| dep.pkg).collect(); diff --git a/src/doc/man/cargo-metadata.adoc b/src/doc/man/cargo-metadata.adoc index 45bd3b73736..cb5bfb579c7 100644 --- a/src/doc/man/cargo-metadata.adoc +++ b/src/doc/man/cargo-metadata.adoc @@ -199,13 +199,14 @@ The output has the following format: "workspace_members": [ "my-package 0.1.0 (path+file:///path/to/my-package)", ], - /* The resolved dependency graph, with the concrete versions and features - selected. The set depends on the enabled features. - This is null if --no-deps is specified. - By default, this includes all dependencies for all target platforms. - The `--filter-platform` flag may be used to narrow to a specific - target triple. - */ + // The resolved dependency graph, with the concrete versions and features + // selected. The set depends on the enabled features. + // + // This is null if --no-deps is specified. + // + // By default, this includes all dependencies for all target platforms. + // The `--filter-platform` flag may be used to narrow to a specific + // target triple. "resolve": { /* Array of nodes within the dependency graph. Each node is a package. @@ -230,7 +231,20 @@ The output has the following format: */ "name": "bitflags", /* The Package ID of the dependency. */ - "pkg": "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + /* Array of dependency kinds. Added in Cargo 1.40. */ + "dep_kinds": [ + { + /* The dependency kind. + "dev", "build", or null for a normal dependency. + */ + "kind": null, + /* The target platform for the dependency. + null if not a target dependency. + */ + "target": "cfg(windows)" + } + ] } ], /* Array of features enabled on this package. */ diff --git a/src/doc/man/generated/cargo-metadata.html b/src/doc/man/generated/cargo-metadata.html index 7530f323a9f..bc86b267492 100644 --- a/src/doc/man/generated/cargo-metadata.html +++ b/src/doc/man/generated/cargo-metadata.html @@ -206,13 +206,14 @@

OUTPUT FORMAT

"workspace_members": [ "my-package 0.1.0 (path+file:///path/to/my-package)", ], - /* The resolved dependency graph, with the concrete versions and features - selected. The set depends on the enabled features. - This is null if --no-deps is specified. - By default, this includes all dependencies for all target platforms. - The `--filter-platform` flag may be used to narrow to a specific - target triple. - */ + // The resolved dependency graph, with the concrete versions and features + // selected. The set depends on the enabled features. + // + // This is null if --no-deps is specified. + // + // By default, this includes all dependencies for all target platforms. + // The `--filter-platform` flag may be used to narrow to a specific + // target triple. "resolve": { /* Array of nodes within the dependency graph. Each node is a package. @@ -237,7 +238,20 @@

OUTPUT FORMAT

*/ "name": "bitflags", /* The Package ID of the dependency. */ - "pkg": "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + /* Array of dependency kinds. Added in Cargo 1.40. */ + "dep_kinds": [ + { + /* The dependency kind. + "dev", "build", or null for a normal dependency. + */ + "kind": null, + /* The target platform for the dependency. + null if not a target dependency. + */ + "target": "cfg(windows)" + } + ] } ], /* Array of features enabled on this package. */ diff --git a/src/etc/man/cargo-metadata.1 b/src/etc/man/cargo-metadata.1 index 7ab6f89bca2..7589c86a2f5 100644 --- a/src/etc/man/cargo-metadata.1 +++ b/src/etc/man/cargo-metadata.1 @@ -220,13 +220,14 @@ The output has the following format: "workspace_members": [ "my\-package 0.1.0 (path+file:///path/to/my\-package)", ], - /* The resolved dependency graph, with the concrete versions and features - selected. The set depends on the enabled features. - This is null if \-\-no\-deps is specified. - By default, this includes all dependencies for all target platforms. - The `\-\-filter\-platform` flag may be used to narrow to a specific - target triple. - */ + // The resolved dependency graph, with the concrete versions and features + // selected. The set depends on the enabled features. + // + // This is null if \-\-no\-deps is specified. + // + // By default, this includes all dependencies for all target platforms. + // The `\-\-filter\-platform` flag may be used to narrow to a specific + // target triple. "resolve": { /* Array of nodes within the dependency graph. Each node is a package. @@ -251,7 +252,20 @@ The output has the following format: */ "name": "bitflags", /* The Package ID of the dependency. */ - "pkg": "bitflags 1.0.4 (registry+https://github.com/rust\-lang/crates.io\-index)" + "pkg": "bitflags 1.0.4 (registry+https://github.com/rust\-lang/crates.io\-index)", + /* Array of dependency kinds. Added in Cargo 1.40. */ + "dep_kinds": [ + { + /* The dependency kind. + "dev", "build", or null for a normal dependency. + */ + "kind": null, + /* The target platform for the dependency. + null if not a target dependency. + */ + "target": "cfg(windows)" + } + ] } ], /* Array of features enabled on this package. */ diff --git a/tests/testsuite/metadata.rs b/tests/testsuite/metadata.rs index d56c70e00f9..47c9e9b84e1 100644 --- a/tests/testsuite/metadata.rs +++ b/tests/testsuite/metadata.rs @@ -486,10 +486,22 @@ fn cargo_metadata_with_deps_and_version() { ], "deps": [ { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], "name": "bar", "pkg": "bar 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" }, { + "dep_kinds": [ + { + "kind": "dev", + "target": null + } + ], "name": "foobar", "pkg": "foobar 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" } @@ -503,6 +515,12 @@ fn cargo_metadata_with_deps_and_version() { ], "deps": [ { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], "name": "baz", "pkg": "baz 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" } @@ -1660,10 +1678,22 @@ fn rename_dependency() { ], "deps": [ { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], "name": "bar", "pkg": "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" }, { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], "name": "baz", "pkg": "bar 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" } @@ -2102,7 +2132,7 @@ fn filter_platform() { "optional": false, "uses_default_features": true, "features": [], - "target": "$ALT", + "target": "$ALT_TRIPLE", "registry": null }, { @@ -2114,7 +2144,7 @@ fn filter_platform() { "optional": false, "uses_default_features": true, "features": [], - "target": "$HOST", + "target": "$HOST_TRIPLE", "registry": null } ], @@ -2145,8 +2175,8 @@ fn filter_platform() { "links": null } "# - .replace("$ALT", &alternate()) - .replace("$HOST", &rustc_host()); + .replace("$ALT_TRIPLE", &alternate()) + .replace("$HOST_TRIPLE", &rustc_host()); // Normal metadata, no filtering, returns *everything*. p.cargo("metadata") @@ -2188,19 +2218,43 @@ fn filter_platform() { "deps": [ { "name": "alt_dep", - "pkg": "alt-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "alt-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": "$ALT_TRIPLE" + } + ] }, { "name": "cfg_dep", - "pkg": "cfg-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "cfg-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": "cfg(foobar)" + } + ] }, { "name": "host_dep", - "pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": "$HOST_TRIPLE" + } + ] }, { "name": "normal_dep", - "pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] } ], "features": [] @@ -2225,6 +2279,8 @@ fn filter_platform() { "workspace_root": "[..]/foo" } "# + .replace("$ALT_TRIPLE", &alternate()) + .replace("$HOST_TRIPLE", &rustc_host()) .replace("$ALT_DEP", alt_dep) .replace("$CFG_DEP", cfg_dep) .replace("$HOST_DEP", host_dep) @@ -2262,11 +2318,23 @@ fn filter_platform() { "deps": [ { "name": "alt_dep", - "pkg": "alt-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "alt-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": "$ALT_TRIPLE" + } + ] }, { "name": "normal_dep", - "pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] } ], "features": [] @@ -2285,6 +2353,7 @@ fn filter_platform() { "workspace_root": "[..]foo" } "# + .replace("$ALT_TRIPLE", &alternate()) .replace("$ALT_DEP", alt_dep) .replace("$NORMAL_DEP", normal_dep) .replace("$FOO", &foo), @@ -2314,11 +2383,23 @@ fn filter_platform() { "deps": [ { "name": "host_dep", - "pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": "$HOST_TRIPLE" + } + ] }, { "name": "normal_dep", - "pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] } ], "features": [] @@ -2343,6 +2424,7 @@ fn filter_platform() { "workspace_root": "[..]foo" } "# + .replace("$HOST_TRIPLE", &rustc_host()) .replace("$HOST_DEP", host_dep) .replace("$NORMAL_DEP", normal_dep) .replace("$FOO", &foo), @@ -2381,15 +2463,33 @@ fn filter_platform() { "deps": [ { "name": "cfg_dep", - "pkg": "cfg-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "cfg-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": "cfg(foobar)" + } + ] }, { "name": "host_dep", - "pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "host-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": "$HOST_TRIPLE" + } + ] }, { "name": "normal_dep", - "pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" + "pkg": "normal-dep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] } ], "features": [] @@ -2414,6 +2514,7 @@ fn filter_platform() { "workspace_root": "[..]/foo" } "# + .replace("$HOST_TRIPLE", &rustc_host()) .replace("$CFG_DEP", cfg_dep) .replace("$HOST_DEP", host_dep) .replace("$NORMAL_DEP", normal_dep) @@ -2421,3 +2522,102 @@ fn filter_platform() { ) .run(); } + +#[cargo_test] +fn dep_kinds() { + Package::new("bar", "0.1.0").publish(); + Package::new("winapi", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "0.1" + + [dev-dependencies] + bar = "0.1" + + [build-dependencies] + bar = "0.1" + + [target.'cfg(windows)'.dependencies] + winapi = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("metadata") + .with_json( + r#" +{ + "packages": "{...}", + "workspace_members": "{...}", + "target_directory": "{...}", + "version": 1, + "workspace_root": "{...}", + "resolve": { + "nodes": [ + { + "id": "bar 0.1.0 [..]", + "dependencies": [], + "deps": [], + "features": [] + }, + { + "id": "foo 0.1.0 [..]", + "dependencies": [ + "bar 0.1.0 [..]", + "winapi 0.1.0 [..]" + ], + "deps": [ + { + "name": "bar", + "pkg": "bar 0.1.0 [..]", + "dep_kinds": [ + { + "kind": null, + "target": null + }, + { + "kind": "dev", + "target": null + }, + { + "kind": "build", + "target": null + } + ] + }, + { + "name": "winapi", + "pkg": "winapi 0.1.0 [..]", + "dep_kinds": [ + { + "kind": null, + "target": "cfg(windows)" + } + ] + } + ], + "features": [] + }, + { + "id": "winapi 0.1.0 [..]", + "dependencies": [], + "deps": [], + "features": [] + } + ], + "root": "foo 0.1.0 [..]" + } +} +"#, + ) + .run(); +} diff --git a/tests/testsuite/update.rs b/tests/testsuite/update.rs index 1f7a2ed594b..46c0289a067 100644 --- a/tests/testsuite/update.rs +++ b/tests/testsuite/update.rs @@ -525,6 +525,12 @@ fn update_precise_first_run() { ], "deps": [ { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], "name": "serde", "pkg": "serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" }