diff --git a/src/cargo/core/compiler/context/unit_dependencies.rs b/src/cargo/core/compiler/context/unit_dependencies.rs index 69242009d25..8c87d0a53e5 100644 --- a/src/cargo/core/compiler/context/unit_dependencies.rs +++ b/src/cargo/core/compiler/context/unit_dependencies.rs @@ -122,7 +122,7 @@ fn compute_deps<'a, 'b, 'cfg>( true }) }).filter_map(|(id, _)| match bcx.get_package(id) { - Ok(pkg) => pkg.lib_target().map(|t| { + Ok(pkg) => pkg.targets().iter().find(|t| t.is_lib()).map(|t| { let mode = check_or_build_mode(&unit.mode, t); let unit = new_unit(bcx, pkg, t, profile_for, unit.kind.for_target(t), mode); Ok((unit, profile_for)) @@ -256,7 +256,7 @@ fn compute_deps_doc<'a, 'cfg>( let mut ret = Vec::new(); for dep in deps { let dep = dep?; - let lib = match dep.lib_target() { + let lib = match dep.targets().iter().find(|t| t.is_lib()) { Some(lib) => lib, None => continue, }; diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 475130506c7..37ad259f10b 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -129,10 +129,6 @@ impl Package { pub fn targets(&self) -> &[Target] { self.manifest.targets() } - /// Get the library target for the package - pub fn lib_target(&self) -> Option<&Target> { - self.targets().iter().find(|t| t.is_lib()) - } /// Get the current package version pub fn version(&self) -> &Version { self.package_id().version() diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 3d5fa2c535f..5e60111e8b6 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -542,11 +542,8 @@ fn generate_targets<'a>( proposals.extend(default_units); if build_config.mode == CompileMode::Test { // Include the lib as it will be required for doctests. - match pkg.lib_target() { - Some(t) if t.doctested() => { - proposals.push((new_unit(pkg, t, CompileMode::Build), false)); - } - _ => {} + if let Some(t) = pkg.targets().iter().find(|t| t.is_lib() && t.doctested()) { + proposals.push((new_unit(pkg, t, CompileMode::Build), false)); } } } @@ -559,7 +556,7 @@ fn generate_targets<'a>( ref benches, } => { if lib { - if let Some(target) = pkg.lib_target() { + if let Some(target) = pkg.targets().iter().find(|t| t.is_lib()) { proposals.push((new_unit(pkg, target, build_config.mode), false)); } else if !all_targets { bail!("no library targets found") diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index c7d3c3ce851..5cba2d482de 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -1,6 +1,7 @@ +use serde::ser::{self, Serialize}; + use core::resolver::Resolve; -use core::{Package, PackageId, PackageSet, Workspace}; -use core::dependency; +use core::{Package, PackageId, Workspace}; use ops::{self, Packages}; use util::CargoResult; @@ -55,19 +56,18 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult>>()?; + Ok(ExportInfo { packages, workspace_members: ws.members().map(|pkg| pkg.package_id().clone()).collect(), - resolve: Some(resolve), + resolve: Some(MetadataResolve { + resolve, + root: ws.current_opt().map(|pkg| pkg.package_id().clone()), + }), target_directory: ws.target_dir().display().to_string(), version: VERSION, workspace_root: ws.root().display().to_string(), @@ -76,91 +76,42 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult, - /// Packages which are direct members of the current project. workspace_members: Vec, - /// A graph of the dependencies between packages. resolve: Option, - /// The directory where intermediate build artifacts will be stored. target_directory: String, - /// Version of this JSON format version: u32, - /// Path to the directory with the project. workspace_root: String, } -// The serialization format is different from lockfile, because -// here we use different format for `PackageId`s, and give more -// information about dependencies. +/// Newtype wrapper to provide a custom `Serialize` implementation. +/// The one from lockfile does not fit because it uses a non-standard +/// format for `PackageId`s #[derive(Serialize)] struct MetadataResolve { - /// Dependencies for each package from `ExportInfo::package`. - nodes: Vec, - /// Deprecated, use `ExportInfo::workspace_members`. + #[serde(rename = "nodes", serialize_with = "serialize_resolve")] + resolve: Resolve, root: Option, } -/// Describes dependencies of a single package. -#[derive(Serialize)] -struct Node { - /// The id of the package. - id: PackageId, - /// Deprecated, use `deps` field. - dependencies: Vec, - /// Dependencies of this package. - deps: Vec, - /// Features, enabled for this package. - features: Vec, -} - -/// Describes a single dependency. -#[derive(Serialize)] -struct Dependency { - /// The id of the dependency. - id: PackageId, - /// The name used for `extern crate` declaration of this dependency. - name: String, - /// Is this normal, dev or build dependency - kind: dependency::Kind, -} - -impl MetadataResolve { - pub fn new( - packages: &PackageSet, - resolve: &Resolve, - root: Option, - ) -> MetadataResolve { - let nodes = resolve - .iter() - .map(|pkg| { - Node { - id: pkg.clone(), - dependencies: resolve.deps(pkg).map(|(dep, _)| dep.clone()).collect(), - deps: resolve - .deps(pkg) - .flat_map(|(id, deps)| { - let dep_name = packages.get(id).unwrap() - .lib_target().unwrap() - .crate_name(); - deps.iter().map(|dep| { - Dependency { - id: id.clone(), - name: dep.rename().unwrap_or(&dep_name) - .to_owned(), - kind: dep.kind(), - } - }).collect::>().into_iter() - }) - .collect(), - features: resolve - .features_sorted(pkg) - .into_iter() - .map(|s| s.to_string()) - .collect(), - } - }) - .collect(); - MetadataResolve { nodes, root } +fn serialize_resolve(resolve: &Resolve, s: S) -> Result +where + S: ser::Serializer, +{ + #[derive(Serialize)] + struct Node<'a> { + id: &'a PackageId, + dependencies: Vec<&'a PackageId>, + features: Vec<&'a str>, } + + resolve + .iter() + .map(|id| Node { + id, + dependencies: resolve.deps(id).map(|p| p.0).collect(), + features: resolve.features_sorted(id), + }) + .collect::>() + .serialize(s) } diff --git a/tests/testsuite/metadata.rs b/tests/testsuite/metadata.rs index de0c0afb41d..f0b5e104be0 100644 --- a/tests/testsuite/metadata.rs +++ b/tests/testsuite/metadata.rs @@ -1,6 +1,5 @@ use cargotest::support::registry::Package; use cargotest::support::{basic_bin_manifest, basic_lib_manifest, execs, main_file, project}; -use cargotest::ChannelChanger; use hamcrest::assert_that; #[test] @@ -54,7 +53,6 @@ fn cargo_metadata_simple() { "nodes": [ { "dependencies": [], - "deps": [], "features": [], "id": "foo 0.5.0 (path+file:[..]foo)" } @@ -69,204 +67,6 @@ fn cargo_metadata_simple() { ); } -#[test] -fn metadata_with_renamed_crates() { - Package::new("bar", "0.1.0").publish(); - Package::new("bar", "0.2.0").publish(); - - let p = project("foo") - .file( - "Cargo.toml", - r#" - cargo-features = ["rename-dependency"] - - [project] - name = "foo" - version = "0.5.0" - authors = [] - - [dependencies] - bar = { version = "0.1.0" } - baz = { version = "0.2.0", package = "bar" } - "#, - ) - .file( - "src/lib.rs", - " - extern crate bar; - extern crate baz; - ", - ) - .build(); - - assert_that( - p.cargo("metadata").masquerade_as_nightly_cargo(), - execs().with_json( - r#" - { - "packages": "{...}", - "workspace_members": [ - "foo 0.5.0 (path+file:[..]foo)" - ], - "resolve": { - "nodes": [ - { - "dependencies": [], - "deps": [], - "features": [], - "id": "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)" - }, - { - "dependencies": [ - "bar 0.2.0 (registry+/~https://github.com/rust-lang/crates.io-index)", - "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)" - ], - "deps": [ - { - "name": "baz", - "id": "bar 0.2.0 (registry+/~https://github.com/rust-lang/crates.io-index)", - "kind": null - }, - { - "name": "bar", - "id": "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)", - "kind": null - } - ], - "features": [], - "id": "foo 0.5.0 (path+file://[..])" - }, - { - "dependencies": [], - "deps": [], - "features": [], - "id": "bar 0.2.0 (registry+/~https://github.com/rust-lang/crates.io-index)" - } - ], - "root": "foo 0.5.0 (path+file:[..]foo)" - }, - "target_directory": "[..]foo[/]target", - "version": 1, - "workspace_root": "[..][/]foo" - }"#, - ), - ); -} - -#[test] -fn metadata_dep_kinds() { - Package::new("bar", "0.1.0").publish(); - - let p = project("foo") - .file( - "Cargo.toml", - r#" - [project] - name = "foo" - version = "0.5.0" - authors = [] - - [dependencies] - bar = { version = "0.1.0", optional = true } - - [build-dependencies] - bar = { version = "0.1.0"} - "#, - ) - .file("src/lib.rs", "") - .build(); - - assert_that( - p.cargo("metadata"), - execs().with_json( - r#" - { - "packages": "{...}", - "workspace_members": [ - "foo 0.5.0 (path+file:[..]foo)" - ], - "resolve": { - "nodes": [ - { - "dependencies": [], - "deps": [], - "features": [], - "id": "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)" - }, - { - "dependencies": [ - "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)" - ], - "deps": [ - { - "name": "bar", - "id": "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)", - "kind": "build" - } - ], - "features": [], - "id": "foo 0.5.0 (path+file://[..])" - } - ], - "root": "foo 0.5.0 (path+file:[..]foo)" - }, - "target_directory": "[..]foo[/]target", - "version": 1, - "workspace_root": "[..][/]foo" - }"#, - ), - ); - - assert_that( - p.cargo("metadata --all-features"), - execs().with_json( - r#" - { - "packages": "{...}", - "workspace_members": [ - "foo 0.5.0 (path+file:[..]foo)" - ], - "resolve": { - "nodes": [ - { - "dependencies": [], - "deps": [], - "features": [], - "id": "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)" - }, - { - "dependencies": [ - "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)" - ], - "deps": [ - { - "name": "bar", - "id": "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)", - "kind": "build" - }, - { - "name": "bar", - "id": "bar 0.1.0 (registry+/~https://github.com/rust-lang/crates.io-index)", - "kind": null - } - ], - "features": [ "bar" ], - "id": "foo 0.5.0 (path+file://[..])" - } - ], - "root": "foo 0.5.0 (path+file:[..]foo)" - }, - "target_directory": "[..]foo[/]target", - "version": 1, - "workspace_root": "[..][/]foo" - }"#, - ), - ); - -} - - - #[test] fn cargo_metadata_warns_on_implicit_version() { let p = project("foo") @@ -344,7 +144,6 @@ crate-type = ["lib", "staticlib"] "nodes": [ { "dependencies": [], - "deps": [], "features": [], "id": "foo 0.5.0 (path+file:[..]foo)" } @@ -426,7 +225,6 @@ optional_feat = [] "nodes": [ { "dependencies": [], - "deps": [], "features": [ "default", "default_feat" @@ -601,13 +399,6 @@ fn cargo_metadata_with_deps_and_version() { "dependencies": [ "bar 0.0.1 (registry+[..])" ], - "deps": [ - { - "id": "bar 0.0.1 (registry+[..])", - "name": "bar", - "kind": null - } - ], "features": [], "id": "foo 0.5.0 (path+file:[..]foo)" }, @@ -615,19 +406,11 @@ fn cargo_metadata_with_deps_and_version() { "dependencies": [ "baz 0.0.1 (registry+[..])" ], - "deps": [ - { - "id": "baz 0.0.1 (registry+[..])", - "name": "baz", - "kind": null - } - ], "features": [], "id": "bar 0.0.1 (registry+[..])" }, { "dependencies": [], - "deps": [], "features": [], "id": "baz 0.0.1 (registry+[..])" } @@ -708,8 +491,7 @@ name = "ex" { "id": "foo 0.1.0 (path+file:[..]foo)", "features": [], - "dependencies": [], - "deps": [] + "dependencies": [] } ] }, @@ -788,8 +570,7 @@ crate-type = ["rlib", "dylib"] { "id": "foo 0.1.0 (path+file:[..]foo)", "features": [], - "dependencies": [], - "deps": [] + "dependencies": [] } ] }, @@ -885,13 +666,11 @@ fn workspace_metadata() { "nodes": [ { "dependencies": [], - "deps": [], "features": [], "id": "baz 0.5.0 (path+file:[..]baz)" }, { "dependencies": [], - "deps": [], "features": [], "id": "bar 0.5.0 (path+file:[..]bar)" }