1
+ use crate :: core:: compiler:: artifact:: match_artifacts_kind_with_targets;
1
2
use crate :: core:: compiler:: { CompileKind , RustcTargetData } ;
2
3
use crate :: core:: dependency:: DepKind ;
3
4
use crate :: core:: package:: SerializedPackage ;
4
5
use crate :: core:: resolver:: { features:: CliFeatures , HasDevUnits , Resolve } ;
5
- use crate :: core:: { Dependency , Package , PackageId , Workspace } ;
6
+ use crate :: core:: { Package , PackageId , Workspace } ;
6
7
use crate :: ops:: { self , Packages } ;
7
8
use crate :: util:: interning:: InternedString ;
8
9
use crate :: util:: CargoResult ;
@@ -81,6 +82,8 @@ struct MetadataResolveNode {
81
82
82
83
#[ derive( Serialize ) ]
83
84
struct Dep {
85
+ // TODO(bindeps): after -Zbindeps gets stabilized,
86
+ // mark this field as deprecated in the help manual of cargo-metadata
84
87
name : InternedString ,
85
88
pkg : PackageId ,
86
89
dep_kinds : Vec < DepKindInfo > ,
@@ -90,15 +93,27 @@ struct Dep {
90
93
struct DepKindInfo {
91
94
kind : DepKind ,
92
95
target : Option < Platform > ,
93
- }
94
96
95
- impl From < & Dependency > for DepKindInfo {
96
- fn from ( dep : & Dependency ) -> DepKindInfo {
97
- DepKindInfo {
98
- kind : dep. kind ( ) ,
99
- target : dep. platform ( ) . cloned ( ) ,
100
- }
101
- }
97
+ // vvvvv The fields below are introduced for `-Z bindeps`.
98
+ /// What the manifest calls the crate.
99
+ ///
100
+ /// A renamed dependency will show the rename instead of original name.
101
+ // TODO(bindeps): Remove `Option` after -Zbindeps get stabilized.
102
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
103
+ extern_name : Option < InternedString > ,
104
+ /// Artifact's crate type, e.g. staticlib, cdylib, bin...
105
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
106
+ artifact : Option < & ' static str > ,
107
+ /// Equivalent to `{ target = "…" }` in an artifact dependency requirement.
108
+ ///
109
+ /// * If the target points to a custom target JSON file, the path will be absolute.
110
+ /// * If the target is a build assumed target `{ target = "target" }`, it will show as `<target>`.
111
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
112
+ compile_target : Option < InternedString > ,
113
+ /// Executable name for an artifact binary dependency.
114
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
115
+ bin_name : Option < String > ,
116
+ // ^^^^^ The fields above are introduced for `-Z bindeps`.
102
117
}
103
118
104
119
/// Builds the resolve graph as it will be displayed to the user.
@@ -149,7 +164,7 @@ fn build_resolve_graph(
149
164
& package_map,
150
165
& target_data,
151
166
& requested_kinds,
152
- ) ;
167
+ ) ? ;
153
168
}
154
169
// Get a Vec of Packages.
155
170
let actual_packages = package_map
@@ -172,9 +187,9 @@ fn build_resolve_graph_r(
172
187
package_map : & BTreeMap < PackageId , Package > ,
173
188
target_data : & RustcTargetData < ' _ > ,
174
189
requested_kinds : & [ CompileKind ] ,
175
- ) {
190
+ ) -> CargoResult < ( ) > {
176
191
if node_map. contains_key ( & pkg_id) {
177
- return ;
192
+ return Ok ( ( ) ) ;
178
193
}
179
194
// This normalizes the IDs so that they are consistent between the
180
195
// `packages` array and the `resolve` map. This is a bit of a hack to
@@ -193,9 +208,9 @@ fn build_resolve_graph_r(
193
208
let normalize_id = |id| -> PackageId { * package_map. get_key_value ( & id) . unwrap ( ) . 0 } ;
194
209
let features = resolve. features ( pkg_id) . to_vec ( ) ;
195
210
196
- let deps: Vec < Dep > = resolve
197
- . deps ( pkg_id )
198
- . filter ( |( _dep_id, deps) | {
211
+ let deps = {
212
+ let mut dep_metadatas = Vec :: new ( ) ;
213
+ let iter = resolve . deps ( pkg_id ) . filter ( |( _dep_id, deps) | {
199
214
if requested_kinds == [ CompileKind :: Host ] {
200
215
true
201
216
} else {
@@ -204,27 +219,109 @@ fn build_resolve_graph_r(
204
219
. any ( |dep| target_data. dep_platform_activated ( dep, * kind) )
205
220
} )
206
221
}
207
- } )
208
- . filter_map ( |( dep_id, deps) | {
209
- let mut dep_kinds: Vec < _ > = deps. iter ( ) . map ( DepKindInfo :: from) . collect ( ) ;
222
+ } ) ;
223
+ for ( dep_id, deps) in iter {
224
+ let mut dep_kinds = Vec :: new ( ) ;
225
+
226
+ let targets = package_map[ & dep_id] . targets ( ) ;
227
+
228
+ // Try to get the extern name for lib, or crate name for bins.
229
+ let extern_name = |target| {
230
+ resolve
231
+ . extern_crate_name_and_dep_name ( pkg_id, dep_id, target)
232
+ . map ( |( ext_crate_name, _) | ext_crate_name)
233
+ } ;
234
+
235
+ let lib_target = targets. iter ( ) . find ( |t| t. is_lib ( ) ) ;
236
+
237
+ for dep in deps. iter ( ) {
238
+ if let Some ( target) = lib_target {
239
+ // When we do have a library target, include them in deps if...
240
+ let included = match dep. artifact ( ) {
241
+ // it is not an artifact dep at all
242
+ None => true ,
243
+ // it is also an artifact dep with `{ …, lib = true }`
244
+ Some ( a) if a. is_lib ( ) => true ,
245
+ _ => false ,
246
+ } ;
247
+ // TODO(bindeps): Cargo shouldn't have `extern_name` field
248
+ // if the user is not using -Zbindeps.
249
+ // Remove this condition ` after -Zbindeps gets stabilized.
250
+ let extern_name = if dep. artifact ( ) . is_some ( ) {
251
+ Some ( extern_name ( target) ?)
252
+ } else {
253
+ None
254
+ } ;
255
+ if included {
256
+ dep_kinds. push ( DepKindInfo {
257
+ kind : dep. kind ( ) ,
258
+ target : dep. platform ( ) . cloned ( ) ,
259
+ extern_name,
260
+ artifact : None ,
261
+ compile_target : None ,
262
+ bin_name : None ,
263
+ } ) ;
264
+ }
265
+ }
266
+
267
+ // No need to proceed if there is no artifact dependency.
268
+ let Some ( artifact_requirements) = dep. artifact ( ) else {
269
+ continue ;
270
+ } ;
271
+
272
+ let compile_target = match artifact_requirements. target ( ) {
273
+ Some ( t) => t
274
+ . to_compile_target ( )
275
+ . map ( |t| t. rustc_target ( ) )
276
+ // Given that Cargo doesn't know which target it should resolve to,
277
+ // when an artifact dep is specified with { target = "target" },
278
+ // keep it with a special "<target>" string,
279
+ . or_else ( || Some ( InternedString :: new ( "<target>" ) ) ) ,
280
+ None => None ,
281
+ } ;
282
+
283
+ let target_set =
284
+ match_artifacts_kind_with_targets ( dep, targets, pkg_id. name ( ) . as_str ( ) ) ?;
285
+ dep_kinds. reserve ( target_set. len ( ) ) ;
286
+ for ( kind, target) in target_set. into_iter ( ) {
287
+ dep_kinds. push ( DepKindInfo {
288
+ kind : dep. kind ( ) ,
289
+ target : dep. platform ( ) . cloned ( ) ,
290
+ extern_name : extern_name ( target) . ok ( ) ,
291
+ artifact : Some ( kind. crate_type ( ) ) ,
292
+ compile_target,
293
+ bin_name : target. is_bin ( ) . then ( || target. name ( ) . to_string ( ) ) ,
294
+ } )
295
+ }
296
+ }
297
+
210
298
dep_kinds. sort ( ) ;
211
- package_map
212
- . get ( & dep_id)
213
- . and_then ( |pkg| pkg. targets ( ) . iter ( ) . find ( |t| t. is_lib ( ) ) )
214
- . and_then ( |lib_target| {
215
- resolve
216
- . extern_crate_name_and_dep_name ( pkg_id, dep_id, lib_target)
217
- . map ( |( ext_crate_name, _) | ext_crate_name)
218
- . ok ( )
219
- } )
220
- . map ( |name| Dep {
221
- name,
222
- pkg : normalize_id ( dep_id) ,
299
+
300
+ let pkg = normalize_id ( dep_id) ;
301
+
302
+ let dep = match ( lib_target, dep_kinds. len ( ) ) {
303
+ ( Some ( target) , _) => Dep {
304
+ name : extern_name ( target) ?,
305
+ pkg,
223
306
dep_kinds,
224
- } )
225
- } )
226
- . collect ( ) ;
227
- let dumb_deps: Vec < PackageId > = deps. iter ( ) . map ( |dep| normalize_id ( dep. pkg ) ) . collect ( ) ;
307
+ } ,
308
+ // No lib target exists but contains artifact deps.
309
+ ( None , 1 ..) => Dep {
310
+ name : InternedString :: new ( "" ) ,
311
+ pkg,
312
+ dep_kinds,
313
+ } ,
314
+ // No lib or artifact dep exists.
315
+ // Ususally this mean parent depending on non-lib bin crate.
316
+ ( None , _) => continue ,
317
+ } ;
318
+
319
+ dep_metadatas. push ( dep)
320
+ }
321
+ dep_metadatas
322
+ } ;
323
+
324
+ let dumb_deps: Vec < PackageId > = deps. iter ( ) . map ( |dep| dep. pkg ) . collect ( ) ;
228
325
let to_visit = dumb_deps. clone ( ) ;
229
326
let node = MetadataResolveNode {
230
327
id : normalize_id ( pkg_id) ,
@@ -241,6 +338,8 @@ fn build_resolve_graph_r(
241
338
package_map,
242
339
target_data,
243
340
requested_kinds,
244
- ) ;
341
+ ) ? ;
245
342
}
343
+
344
+ Ok ( ( ) )
246
345
}
0 commit comments