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))
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,
};
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()
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));
}
}
}
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")
+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;
)?;
let (packages, resolve) = deps;
- let resolve = MetadataResolve::new(
- &packages,
- &resolve,
- ws.current_opt().map(|pkg| pkg.package_id().clone()),
- );
let packages = packages
.package_ids()
.map(|i| packages.get(i).map(|p| p.clone()))
.collect::<CargoResult<Vec<_>>>()?;
+
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(),
#[derive(Serialize)]
pub struct ExportInfo {
- /// All packages for this project, with dependencies.
packages: Vec<Package>,
- /// Packages which are direct members of the current project.
workspace_members: Vec<PackageId>,
- /// A graph of the dependencies between packages.
resolve: Option<MetadataResolve>,
- /// 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<Node>,
- /// Deprecated, use `ExportInfo::workspace_members`.
+ #[serde(rename = "nodes", serialize_with = "serialize_resolve")]
+ resolve: Resolve,
root: Option<PackageId>,
}
-/// Describes dependencies of a single package.
-#[derive(Serialize)]
-struct Node {
- /// The id of the package.
- id: PackageId,
- /// Deprecated, use `deps` field.
- dependencies: Vec<PackageId>,
- /// Dependencies of this package.
- deps: Vec<Dependency>,
- /// Features, enabled for this package.
- features: Vec<String>,
-}
-
-/// 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<PackageId>,
- ) -> 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::<Vec<_>>().into_iter()
- })
- .collect(),
- features: resolve
- .features_sorted(pkg)
- .into_iter()
- .map(|s| s.to_string())
- .collect(),
- }
- })
- .collect();
- MetadataResolve { nodes, root }
+fn serialize_resolve<S>(resolve: &Resolve, s: S) -> Result<S::Ok, S::Error>
+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::<Vec<_>>()
+ .serialize(s)
}
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]
"nodes": [
{
"dependencies": [],
- "deps": [],
"features": [],
"id": "foo 0.5.0 (path+file:[..]foo)"
}
);
}
-#[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")
"nodes": [
{
"dependencies": [],
- "deps": [],
"features": [],
"id": "foo 0.5.0 (path+file:[..]foo)"
}
"nodes": [
{
"dependencies": [],
- "deps": [],
"features": [
"default",
"default_feat"
"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)"
},
"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+[..])"
}
{
"id": "foo 0.1.0 (path+file:[..]foo)",
"features": [],
- "dependencies": [],
- "deps": []
+ "dependencies": []
}
]
},
{
"id": "foo 0.1.0 (path+file:[..]foo)",
"features": [],
- "dependencies": [],
- "deps": []
+ "dependencies": []
}
]
},
"nodes": [
{
"dependencies": [],
- "deps": [],
"features": [],
"id": "baz 0.5.0 (path+file:[..]baz)"
},
{
"dependencies": [],
- "deps": [],
"features": [],
"id": "bar 0.5.0 (path+file:[..]bar)"
}