Skip to content

Commit d0d3cb5

Browse files
committed
Auto merge of #5461 - matklad:meta-rename, r=alexcrichton
Support crate renames in `cargo metadata` This adds information about (currently unstable) crate renames to metadata. Unfortunately, we already expose dependencies as a list of package ids (which are strings), so we can't easily add a `rename` field easily. For this reason, I've added a parallel `deps` key, which basically deprecates `dependencies` field. So, the new format looks like this ```JavaScript { "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": [ { "extern_crate_name": "baz", // this one is actually renamed "id": "bar 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" }, { "extern_crate_name": "bar", "id": "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" } ], "features": [], "id": "foo 0.5.0 (path+file://[..])" }, ``` Questions: * Is there a better name for `extern_crate_name`? This name is precise, but it's longer than I like, and might become opaque in meaning if we remove `extern crate` from the language :) * Should we feature gate this (i.e, only produce `deps` if we have a feature in `Cargo.toml`)? I think the answer is yes, but that'll require threading `Features` to `Workspace`... r? @alexcrichton
2 parents 757112c + a312c55 commit d0d3cb5

File tree

5 files changed

+316
-39
lines changed

5 files changed

+316
-39
lines changed

src/cargo/core/compiler/context/unit_dependencies.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ fn compute_deps<'a, 'b, 'cfg>(
122122
true
123123
})
124124
}).filter_map(|(id, _)| match bcx.get_package(id) {
125-
Ok(pkg) => pkg.targets().iter().find(|t| t.is_lib()).map(|t| {
125+
Ok(pkg) => pkg.lib_target().map(|t| {
126126
let mode = check_or_build_mode(&unit.mode, t);
127127
let unit = new_unit(bcx, pkg, t, profile_for, unit.kind.for_target(t), mode);
128128
Ok((unit, profile_for))
@@ -222,7 +222,7 @@ fn compute_deps_doc<'a, 'cfg>(
222222
let mut ret = Vec::new();
223223
for dep in deps {
224224
let dep = dep?;
225-
let lib = match dep.targets().iter().find(|t| t.is_lib()) {
225+
let lib = match dep.lib_target() {
226226
Some(lib) => lib,
227227
None => continue,
228228
};

src/cargo/core/package.rs

+4
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ impl Package {
129129
pub fn targets(&self) -> &[Target] {
130130
self.manifest.targets()
131131
}
132+
/// Get the library target for the package
133+
pub fn lib_target(&self) -> Option<&Target> {
134+
self.targets().iter().find(|t| t.is_lib())
135+
}
132136
/// Get the current package version
133137
pub fn version(&self) -> &Version {
134138
self.package_id().version()

src/cargo/ops/cargo_compile.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -546,8 +546,11 @@ fn generate_targets<'a>(
546546
proposals.extend(default_units);
547547
if build_config.mode == CompileMode::Test {
548548
// Include the lib as it will be required for doctests.
549-
if let Some(t) = pkg.targets().iter().find(|t| t.is_lib() && t.doctested()) {
550-
proposals.push((new_unit(pkg, t, CompileMode::Build), false));
549+
match pkg.lib_target() {
550+
Some(t) if t.doctested() => {
551+
proposals.push((new_unit(pkg, t, CompileMode::Build), false));
552+
}
553+
_ => {}
551554
}
552555
}
553556
}
@@ -560,7 +563,7 @@ fn generate_targets<'a>(
560563
ref benches,
561564
} => {
562565
if lib {
563-
if let Some(target) = pkg.targets().iter().find(|t| t.is_lib()) {
566+
if let Some(target) = pkg.lib_target() {
564567
proposals.push((new_unit(pkg, target, build_config.mode), false));
565568
} else if !all_targets {
566569
bail!("no library targets found")

src/cargo/ops/cargo_output_metadata.rs

+81-32
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use serde::ser::{self, Serialize};
2-
31
use core::resolver::Resolve;
4-
use core::{Package, PackageId, Workspace};
2+
use core::{Package, PackageId, PackageSet, Workspace};
3+
use core::dependency;
54
use ops::{self, Packages};
65
use util::CargoResult;
76

@@ -56,18 +55,19 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult<Exp
5655
)?;
5756
let (packages, resolve) = deps;
5857

58+
let resolve = MetadataResolve::new(
59+
&packages,
60+
&resolve,
61+
ws.current_opt().map(|pkg| pkg.package_id().clone()),
62+
);
5963
let packages = packages
6064
.package_ids()
6165
.map(|i| packages.get(i).map(|p| p.clone()))
6266
.collect::<CargoResult<Vec<_>>>()?;
63-
6467
Ok(ExportInfo {
6568
packages,
6669
workspace_members: ws.members().map(|pkg| pkg.package_id().clone()).collect(),
67-
resolve: Some(MetadataResolve {
68-
resolve,
69-
root: ws.current_opt().map(|pkg| pkg.package_id().clone()),
70-
}),
70+
resolve: Some(resolve),
7171
target_directory: ws.target_dir().display().to_string(),
7272
version: VERSION,
7373
workspace_root: ws.root().display().to_string(),
@@ -76,42 +76,91 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult<Exp
7676

7777
#[derive(Serialize)]
7878
pub struct ExportInfo {
79+
/// All packages for this project, with dependencies.
7980
packages: Vec<Package>,
81+
/// Packages which are direct members of the current project.
8082
workspace_members: Vec<PackageId>,
83+
/// A graph of the dependencies between packages.
8184
resolve: Option<MetadataResolve>,
85+
/// The directory where intermediate build artifacts will be stored.
8286
target_directory: String,
87+
/// Version of this JSON format
8388
version: u32,
89+
/// Path to the directory with the project.
8490
workspace_root: String,
8591
}
8692

87-
/// Newtype wrapper to provide a custom `Serialize` implementation.
88-
/// The one from lockfile does not fit because it uses a non-standard
89-
/// format for `PackageId`s
93+
// The serialization format is different from lockfile, because
94+
// here we use different format for `PackageId`s, and give more
95+
// information about dependencies.
9096
#[derive(Serialize)]
9197
struct MetadataResolve {
92-
#[serde(rename = "nodes", serialize_with = "serialize_resolve")]
93-
resolve: Resolve,
98+
/// Dependencies for each package from `ExportInfo::package`.
99+
nodes: Vec<Node>,
100+
/// Deprecated, use `ExportInfo::workspace_members`.
94101
root: Option<PackageId>,
95102
}
96103

97-
fn serialize_resolve<S>(resolve: &Resolve, s: S) -> Result<S::Ok, S::Error>
98-
where
99-
S: ser::Serializer,
100-
{
101-
#[derive(Serialize)]
102-
struct Node<'a> {
103-
id: &'a PackageId,
104-
dependencies: Vec<&'a PackageId>,
105-
features: Vec<&'a str>,
106-
}
104+
/// Describes dependencies of a single package.
105+
#[derive(Serialize)]
106+
struct Node {
107+
/// The id of the package.
108+
id: PackageId,
109+
/// Deprecated, use `deps` field.
110+
dependencies: Vec<PackageId>,
111+
/// Dependencies of this package.
112+
deps: Vec<Dependency>,
113+
/// Features, enabled for this package.
114+
features: Vec<String>,
115+
}
107116

108-
resolve
109-
.iter()
110-
.map(|id| Node {
111-
id,
112-
dependencies: resolve.deps(id).map(|p| p.0).collect(),
113-
features: resolve.features_sorted(id),
114-
})
115-
.collect::<Vec<_>>()
116-
.serialize(s)
117+
/// Describes a single dependency.
118+
#[derive(Serialize)]
119+
struct Dependency {
120+
/// The id of the dependency.
121+
id: PackageId,
122+
/// The name used for `extern crate` declaration of this dependency.
123+
name: String,
124+
/// Is this normal, dev or build dependency
125+
kind: dependency::Kind,
126+
}
127+
128+
impl MetadataResolve {
129+
pub fn new(
130+
packages: &PackageSet,
131+
resolve: &Resolve,
132+
root: Option<PackageId>,
133+
) -> MetadataResolve {
134+
let nodes = resolve
135+
.iter()
136+
.map(|pkg| {
137+
Node {
138+
id: pkg.clone(),
139+
dependencies: resolve.deps(pkg).map(|(dep, _)| dep.clone()).collect(),
140+
deps: resolve
141+
.deps(pkg)
142+
.flat_map(|(id, deps)| {
143+
let dep_name = packages.get(id).unwrap()
144+
.lib_target().unwrap()
145+
.crate_name();
146+
deps.iter().map(|dep| {
147+
Dependency {
148+
id: id.clone(),
149+
name: dep.rename().unwrap_or(&dep_name)
150+
.to_owned(),
151+
kind: dep.kind(),
152+
}
153+
}).collect::<Vec<_>>().into_iter()
154+
})
155+
.collect(),
156+
features: resolve
157+
.features_sorted(pkg)
158+
.into_iter()
159+
.map(|s| s.to_string())
160+
.collect(),
161+
}
162+
})
163+
.collect();
164+
MetadataResolve { nodes, root }
165+
}
117166
}

0 commit comments

Comments
 (0)