Skip to content

Commit 7367e43

Browse files
author
Jon Gjengset
committed
Make cargo metadata and tree respect target
Previously, the `metadata` and `tree` subcommands would download dependencies for all targets, regardless of whether those targets were actually enabled. This PR updates them so that they only download the same dependencies that building would do with the requested target(s). `cargo metadata` still includes all targets by default; you can only opt _out_ using `--filter-platform`. Ideally it should use `--target` the same way `tree` does, but it's too late to change that now. Fixes #8981.
1 parent de42302 commit 7367e43

File tree

5 files changed

+55
-22
lines changed

5 files changed

+55
-22
lines changed

src/cargo/core/package.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ impl<'cfg> PackageSet<'cfg> {
490490
requested_kinds: &[CompileKind],
491491
target_data: &RustcTargetData,
492492
force_all_targets: ForceAllTargets,
493-
) -> CargoResult<()> {
493+
) -> CargoResult<Vec<&Package>> {
494494
fn collect_used_deps(
495495
used: &mut BTreeSet<PackageId>,
496496
resolve: &Resolve,
@@ -554,8 +554,7 @@ impl<'cfg> PackageSet<'cfg> {
554554
force_all_targets,
555555
)?;
556556
}
557-
self.get_many(to_download.into_iter())?;
558-
Ok(())
557+
self.get_many(to_download.into_iter())
559558
}
560559

561560
pub fn sources(&self) -> Ref<'_, SourceMap<'cfg>> {

src/cargo/ops/cargo_output_metadata.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::core::compiler::{CompileKind, RustcTargetData};
22
use crate::core::dependency::DepKind;
33
use crate::core::package::SerializedPackage;
4-
use crate::core::resolver::{HasDevUnits, Resolve, ResolveOpts};
4+
use crate::core::resolver::{features::RequestedFeatures, HasDevUnits, Resolve, ResolveOpts};
55
use crate::core::{Dependency, Package, PackageId, Workspace};
66
use crate::ops::{self, Packages};
77
use crate::util::interning::InternedString;
@@ -115,27 +115,46 @@ fn build_resolve_graph(
115115
let target_data = RustcTargetData::new(ws, &requested_kinds)?;
116116
// Resolve entire workspace.
117117
let specs = Packages::All.to_package_id_specs(ws)?;
118+
let requested_features = RequestedFeatures::from_command_line(
119+
&metadata_opts.features,
120+
metadata_opts.all_features,
121+
!metadata_opts.no_default_features,
122+
);
118123
let resolve_opts = ResolveOpts::new(
119124
/*dev_deps*/ true,
120125
&metadata_opts.features,
121126
metadata_opts.all_features,
122127
!metadata_opts.no_default_features,
123128
);
129+
let force_all = if metadata_opts.filter_platforms.is_empty() {
130+
crate::core::resolver::features::ForceAllTargets::Yes
131+
} else {
132+
crate::core::resolver::features::ForceAllTargets::No
133+
};
124134
let ws_resolve = ops::resolve_ws_with_opts(
125135
ws,
126136
&target_data,
127137
&requested_kinds,
128138
&resolve_opts,
129139
&specs,
130140
HasDevUnits::Yes,
131-
crate::core::resolver::features::ForceAllTargets::No,
141+
force_all,
132142
)?;
133-
// Download all Packages. This is needed to serialize the information
134-
// for every package. In theory this could honor target filtering,
135-
// but that would be somewhat complex.
143+
144+
// Download all Packages. This is needed to serialize the information for every package.
136145
let package_map: BTreeMap<PackageId, Package> = ws_resolve
137146
.pkg_set
138-
.get_many(ws_resolve.pkg_set.package_ids())?
147+
.download_accessible(
148+
&ws_resolve.targeted_resolve,
149+
&ws.members_with_features(&specs, &requested_features)?
150+
.into_iter()
151+
.map(|(p, _)| p.package_id())
152+
.collect::<Vec<_>>(),
153+
HasDevUnits::Yes,
154+
&requested_kinds,
155+
&target_data,
156+
force_all,
157+
)?
139158
.into_iter()
140159
// This is a little lazy, but serde doesn't handle Rc fields very well.
141160
.map(|pkg| (pkg.package_id(), Package::clone(pkg)))

src/cargo/ops/tree/graph.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,13 @@ fn add_pkg(
351351
true
352352
})
353353
.collect();
354+
355+
// This dependency is eliminated from the dependency tree under
356+
// the current target and feature set.
357+
if deps.is_empty() {
358+
continue;
359+
}
360+
354361
deps.sort_unstable_by_key(|dep| dep.name_in_toml());
355362
let dep_pkg = graph.package_map[&dep_id];
356363

src/cargo/ops/tree/mod.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
use self::format::Pattern;
44
use crate::core::compiler::{CompileKind, RustcTargetData};
55
use crate::core::dependency::DepKind;
6-
use crate::core::resolver::{ForceAllTargets, HasDevUnits, ResolveOpts};
6+
use crate::core::resolver::{
7+
features::RequestedFeatures, ForceAllTargets, HasDevUnits, ResolveOpts,
8+
};
79
use crate::core::{Package, PackageId, PackageIdSpec, Workspace};
810
use crate::ops::{self, Packages};
911
use crate::util::{CargoResult, Config};
@@ -136,6 +138,11 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
136138
let requested_kinds = CompileKind::from_requested_targets(ws.config(), &requested_targets)?;
137139
let target_data = RustcTargetData::new(ws, &requested_kinds)?;
138140
let specs = opts.packages.to_package_id_specs(ws)?;
141+
let requested_features = RequestedFeatures::from_command_line(
142+
&opts.features,
143+
opts.all_features,
144+
!opts.no_default_features,
145+
);
139146
let resolve_opts = ResolveOpts::new(
140147
/*dev_deps*/ true,
141148
&opts.features,
@@ -164,12 +171,23 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
164171
has_dev,
165172
force_all,
166173
)?;
174+
167175
// Download all Packages. Some display formats need to display package metadata.
168176
// This may trigger some unnecessary downloads, but trying to figure out a
169177
// minimal set would be difficult.
170178
let package_map: HashMap<PackageId, &Package> = ws_resolve
171179
.pkg_set
172-
.get_many(ws_resolve.pkg_set.package_ids())?
180+
.download_accessible(
181+
&ws_resolve.targeted_resolve,
182+
&ws.members_with_features(&specs, &requested_features)?
183+
.into_iter()
184+
.map(|(p, _)| p.package_id())
185+
.collect::<Vec<_>>(),
186+
has_dev,
187+
&requested_kinds,
188+
&target_data,
189+
force_all,
190+
)?
173191
.into_iter()
174192
.map(|pkg| (pkg.package_id(), pkg))
175193
.collect();

tests/testsuite/features2.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,29 +2214,19 @@ fn minimal_download() {
22142214
.run();
22152215
clear();
22162216

2217-
// This disables itarget, but leaves decouple_dev_deps enabled. However,
2218-
// `cargo tree` downloads everything anyways. Ideally `cargo tree` should
2219-
// be a little smarter, but that would make it a bit more complicated. The
2220-
// two "Downloading" lines are because `download_accessible` doesn't
2221-
// download enough (`cargo tree` really wants everything). Again, that
2222-
// could be cleaner, but is difficult.
2217+
// This disables itarget, but leaves decouple_dev_deps enabled.
22232218
p.cargo("tree -e normal --target=all -Zfeatures=all")
22242219
.masquerade_as_nightly_cargo()
22252220
.with_stderr_unordered(
22262221
"\
22272222
[DOWNLOADING] crates ...
2228-
[DOWNLOADING] crates ...
22292223
[DOWNLOADED] normal v1.0.0 [..]
2230-
[DOWNLOADED] dev_dep v1.0.0 [..]
22312224
[DOWNLOADED] normal_pm v1.0.0 [..]
22322225
[DOWNLOADED] build_dep v1.0.0 [..]
2233-
[DOWNLOADED] dev_dep_pm v1.0.0 [..]
22342226
[DOWNLOADED] build_dep_pm v1.0.0 [..]
22352227
[DOWNLOADED] itarget_normal v1.0.0 [..]
2236-
[DOWNLOADED] itarget_dev_dep v1.0.0 [..]
22372228
[DOWNLOADED] itarget_normal_pm v1.0.0 [..]
22382229
[DOWNLOADED] itarget_build_dep v1.0.0 [..]
2239-
[DOWNLOADED] itarget_dev_dep_pm v1.0.0 [..]
22402230
[DOWNLOADED] itarget_build_dep_pm v1.0.0 [..]
22412231
",
22422232
)

0 commit comments

Comments
 (0)