Skip to content

Support crate renames in cargo metadata #5461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/cargo/core/compiler/context/unit_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ fn compute_deps<'a, 'b, 'cfg>(
true
})
}).filter_map(|(id, _)| match bcx.get_package(id) {
Ok(pkg) => pkg.targets().iter().find(|t| t.is_lib()).map(|t| {
Ok(pkg) => pkg.lib_target().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))
Expand Down Expand Up @@ -222,7 +222,7 @@ fn compute_deps_doc<'a, 'cfg>(
let mut ret = Vec::new();
for dep in deps {
let dep = dep?;
let lib = match dep.targets().iter().find(|t| t.is_lib()) {
let lib = match dep.lib_target() {
Some(lib) => lib,
None => continue,
};
Expand Down
4 changes: 4 additions & 0 deletions src/cargo/core/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ 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()
Expand Down
9 changes: 6 additions & 3 deletions src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,11 @@ fn generate_targets<'a>(
proposals.extend(default_units);
if build_config.mode == CompileMode::Test {
// Include the lib as it will be required for doctests.
if let Some(t) = pkg.targets().iter().find(|t| t.is_lib() && t.doctested()) {
proposals.push((new_unit(pkg, t, CompileMode::Build), false));
match pkg.lib_target() {
Some(t) if t.doctested() => {
proposals.push((new_unit(pkg, t, CompileMode::Build), false));
}
_ => {}
}
}
}
Expand All @@ -560,7 +563,7 @@ fn generate_targets<'a>(
ref benches,
} => {
if lib {
if let Some(target) = pkg.targets().iter().find(|t| t.is_lib()) {
if let Some(target) = pkg.lib_target() {
proposals.push((new_unit(pkg, target, build_config.mode), false));
} else if !all_targets {
bail!("no library targets found")
Expand Down
113 changes: 81 additions & 32 deletions src/cargo/ops/cargo_output_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use serde::ser::{self, Serialize};

use core::resolver::Resolve;
use core::{Package, PackageId, Workspace};
use core::{Package, PackageId, PackageSet, Workspace};
use core::dependency;
use ops::{self, Packages};
use util::CargoResult;

Expand Down Expand Up @@ -56,18 +55,19 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult<Exp
)?;
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(MetadataResolve {
resolve,
root: ws.current_opt().map(|pkg| pkg.package_id().clone()),
}),
resolve: Some(resolve),
target_directory: ws.target_dir().display().to_string(),
version: VERSION,
workspace_root: ws.root().display().to_string(),
Expand All @@ -76,42 +76,91 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult<Exp

#[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,
}

/// 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
// The serialization format is different from lockfile, because
// here we use different format for `PackageId`s, and give more
// information about dependencies.
#[derive(Serialize)]
struct MetadataResolve {
#[serde(rename = "nodes", serialize_with = "serialize_resolve")]
resolve: Resolve,
/// Dependencies for each package from `ExportInfo::package`.
nodes: Vec<Node>,
/// Deprecated, use `ExportInfo::workspace_members`.
root: Option<PackageId>,
}

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>,
}
/// 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>,
}

resolve
.iter()
.map(|id| Node {
id,
dependencies: resolve.deps(id).map(|p| p.0).collect(),
features: resolve.features_sorted(id),
})
.collect::<Vec<_>>()
.serialize(s)
/// 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 }
}
}
Loading