1
- use std:: collections:: HashMap ;
2
- use std:: path:: PathBuf ;
3
-
4
- use serde:: ser;
5
- use serde:: Serialize ;
6
-
1
+ use crate :: core:: compiler:: { CompileKind , CompileTarget , TargetInfo } ;
7
2
use crate :: core:: resolver:: { Resolve , ResolveOpts } ;
8
- use crate :: core:: { Package , PackageId , Workspace } ;
3
+ use crate :: core:: { Dependency , Package , PackageId , Workspace } ;
9
4
use crate :: ops:: { self , Packages } ;
10
5
use crate :: util:: CargoResult ;
6
+ use cargo_platform:: Cfg ;
7
+ use serde:: ser;
8
+ use serde:: Serialize ;
9
+ use std:: collections:: HashMap ;
10
+ use std:: path:: PathBuf ;
11
11
12
12
const VERSION : u32 = 1 ;
13
13
@@ -17,6 +17,7 @@ pub struct OutputMetadataOptions {
17
17
pub all_features : bool ,
18
18
pub no_deps : bool ,
19
19
pub version : u32 ,
20
+ pub filter_platform : Option < String > ,
20
21
}
21
22
22
23
/// Loads the manifest, resolves the dependencies of the package to the concrete
@@ -30,48 +31,63 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo
30
31
VERSION
31
32
) ;
32
33
}
33
- if opt. no_deps {
34
- metadata_no_deps ( ws, opt)
34
+ let ( packages, resolve) = if opt. no_deps {
35
+ let packages = ws. members ( ) . cloned ( ) . collect ( ) ;
36
+ ( packages, None )
35
37
} else {
36
- metadata_full ( ws, opt)
37
- }
38
- }
39
-
40
- fn metadata_no_deps ( ws : & Workspace < ' _ > , _opt : & OutputMetadataOptions ) -> CargoResult < ExportInfo > {
41
- Ok ( ExportInfo {
42
- packages : ws. members ( ) . cloned ( ) . collect ( ) ,
43
- workspace_members : ws. members ( ) . map ( |pkg| pkg. package_id ( ) ) . collect ( ) ,
44
- resolve : None ,
45
- target_directory : ws. target_dir ( ) . into_path_unlocked ( ) ,
46
- version : VERSION ,
47
- workspace_root : ws. root ( ) . to_path_buf ( ) ,
48
- } )
49
- }
50
-
51
- fn metadata_full ( ws : & Workspace < ' _ > , opt : & OutputMetadataOptions ) -> CargoResult < ExportInfo > {
52
- let specs = Packages :: All . to_package_id_specs ( ws) ?;
53
- let opts = ResolveOpts :: new (
54
- /*dev_deps*/ true ,
55
- & opt. features ,
56
- opt. all_features ,
57
- !opt. no_default_features ,
58
- ) ;
59
- let ws_resolve = ops:: resolve_ws_with_opts ( ws, opts, & specs) ?;
60
- let mut packages = HashMap :: new ( ) ;
61
- for pkg in ws_resolve
62
- . pkg_set
63
- . get_many ( ws_resolve. pkg_set . package_ids ( ) ) ?
64
- {
65
- packages. insert ( pkg. package_id ( ) , pkg. clone ( ) ) ;
66
- }
38
+ let specs = Packages :: All . to_package_id_specs ( ws) ?;
39
+ let opts = ResolveOpts :: new (
40
+ /*dev_deps*/ true ,
41
+ & opt. features ,
42
+ opt. all_features ,
43
+ !opt. no_default_features ,
44
+ ) ;
45
+ let ws_resolve = ops:: resolve_ws_with_opts ( ws, opts, & specs) ?;
46
+ let mut package_map = HashMap :: new ( ) ;
47
+ for pkg in ws_resolve
48
+ . pkg_set
49
+ . get_many ( ws_resolve. pkg_set . package_ids ( ) ) ?
50
+ {
51
+ package_map. insert ( pkg. package_id ( ) , pkg. clone ( ) ) ;
52
+ }
53
+ let packages = package_map. values ( ) . map ( |p| ( * p) . clone ( ) ) . collect ( ) ;
54
+ let rustc = ws. config ( ) . load_global_rustc ( Some ( ws) ) ?;
55
+ let ( target, cfg) = match & opt. filter_platform {
56
+ Some ( platform) => {
57
+ if platform == "host" {
58
+ let ti =
59
+ TargetInfo :: new ( ws. config ( ) , CompileKind :: Host , & rustc, CompileKind :: Host ) ?;
60
+ (
61
+ Some ( rustc. host . as_str ( ) . to_string ( ) ) ,
62
+ Some ( ti. cfg ( ) . iter ( ) . cloned ( ) . collect ( ) ) ,
63
+ )
64
+ } else {
65
+ let kind = CompileKind :: Target ( CompileTarget :: new ( platform) ?) ;
66
+ let ti = TargetInfo :: new ( ws. config ( ) , kind, & rustc, kind) ?;
67
+ (
68
+ Some ( platform. clone ( ) ) ,
69
+ Some ( ti. cfg ( ) . iter ( ) . cloned ( ) . collect ( ) ) ,
70
+ )
71
+ }
72
+ }
73
+ None => ( None , None ) ,
74
+ } ;
75
+ let resolve = Some ( MetadataResolve {
76
+ helper : ResolveHelper {
77
+ packages : package_map,
78
+ resolve : ws_resolve. targeted_resolve ,
79
+ target,
80
+ cfg,
81
+ } ,
82
+ root : ws. current_opt ( ) . map ( |pkg| pkg. package_id ( ) ) ,
83
+ } ) ;
84
+ ( packages, resolve)
85
+ } ;
67
86
68
87
Ok ( ExportInfo {
69
- packages : packages . values ( ) . map ( |p| ( * p ) . clone ( ) ) . collect ( ) ,
88
+ packages,
70
89
workspace_members : ws. members ( ) . map ( |pkg| pkg. package_id ( ) ) . collect ( ) ,
71
- resolve : Some ( MetadataResolve {
72
- resolve : ( packages, ws_resolve. targeted_resolve ) ,
73
- root : ws. current_opt ( ) . map ( |pkg| pkg. package_id ( ) ) ,
74
- } ) ,
90
+ resolve,
75
91
target_directory : ws. target_dir ( ) . into_path_unlocked ( ) ,
76
92
version : VERSION ,
77
93
workspace_root : ws. root ( ) . to_path_buf ( ) ,
@@ -94,17 +110,28 @@ pub struct ExportInfo {
94
110
#[ derive( Serialize ) ]
95
111
struct MetadataResolve {
96
112
#[ serde( rename = "nodes" , serialize_with = "serialize_resolve" ) ]
97
- resolve : ( HashMap < PackageId , Package > , Resolve ) ,
113
+ helper : ResolveHelper ,
98
114
root : Option < PackageId > ,
99
115
}
100
116
101
- fn serialize_resolve < S > (
102
- ( packages, resolve) : & ( HashMap < PackageId , Package > , Resolve ) ,
103
- s : S ,
104
- ) -> Result < S :: Ok , S :: Error >
117
+ struct ResolveHelper {
118
+ packages : HashMap < PackageId , Package > ,
119
+ resolve : Resolve ,
120
+ target : Option < String > ,
121
+ cfg : Option < Vec < Cfg > > ,
122
+ }
123
+
124
+ fn serialize_resolve < S > ( helper : & ResolveHelper , s : S ) -> Result < S :: Ok , S :: Error >
105
125
where
106
126
S : ser:: Serializer ,
107
127
{
128
+ let ResolveHelper {
129
+ packages,
130
+ resolve,
131
+ target,
132
+ cfg,
133
+ } = helper;
134
+
108
135
#[ derive( Serialize ) ]
109
136
struct Dep {
110
137
name : String ,
@@ -119,12 +146,30 @@ where
119
146
features : Vec < & ' a str > ,
120
147
}
121
148
149
+ // A filter for removing platform dependencies.
150
+ let dep_filter = |( _pkg, deps) : & ( PackageId , & [ Dependency ] ) | match ( target, cfg) {
151
+ ( Some ( target) , Some ( cfg) ) => deps. iter ( ) . any ( |dep| {
152
+ let platform = match dep. platform ( ) {
153
+ Some ( p) => p,
154
+ None => return true ,
155
+ } ;
156
+ platform. matches ( target, cfg)
157
+ } ) ,
158
+ ( None , None ) => true ,
159
+ _ => unreachable ! ( ) ,
160
+ } ;
161
+
122
162
s. collect_seq ( resolve. iter ( ) . map ( |id| {
123
163
Node {
124
164
id,
125
- dependencies : resolve. deps ( id) . map ( |( pkg, _deps) | pkg) . collect ( ) ,
165
+ dependencies : resolve
166
+ . deps ( id)
167
+ . filter ( dep_filter)
168
+ . map ( |( pkg, _deps) | pkg)
169
+ . collect ( ) ,
126
170
deps : resolve
127
171
. deps ( id)
172
+ . filter ( dep_filter)
128
173
. filter_map ( |( pkg, _deps) | {
129
174
packages
130
175
. get ( & pkg)
0 commit comments