@@ -3,10 +3,11 @@ use std::{cmp, fmt, hash};
3
3
4
4
use core:: compiler:: CompileMode ;
5
5
use core:: interning:: InternedString ;
6
- use core:: { PackageId , PackageIdSpec , PackageSet , Shell } ;
6
+ use core:: { Features , PackageId , PackageIdSpec , PackageSet , Shell } ;
7
+ use util:: errors:: CargoResultExt ;
7
8
use util:: lev_distance:: lev_distance;
8
- use util:: toml:: { ProfilePackageSpec , StringOrBool , TomlProfile , U32OrBool } ;
9
- use util:: CargoResult ;
9
+ use util:: toml:: { ProfilePackageSpec , StringOrBool , TomlProfile , TomlProfiles , U32OrBool } ;
10
+ use util:: { CargoResult , Config } ;
10
11
11
12
/// Collection of all user profiles.
12
13
#[ derive( Clone , Debug ) ]
@@ -20,34 +21,45 @@ pub struct Profiles {
20
21
21
22
impl Profiles {
22
23
pub fn new (
23
- dev : Option < TomlProfile > ,
24
- release : Option < TomlProfile > ,
25
- test : Option < TomlProfile > ,
26
- bench : Option < TomlProfile > ,
27
- doc : Option < TomlProfile > ,
28
- ) -> Profiles {
29
- Profiles {
24
+ profiles : Option < & TomlProfiles > ,
25
+ config : & Config ,
26
+ features : & Features ,
27
+ warnings : & mut Vec < String > ,
28
+ ) -> CargoResult < Profiles > {
29
+ if let Some ( profiles) = profiles {
30
+ profiles. validate ( features, warnings) ?;
31
+ }
32
+
33
+ let config_profiles = config. profiles ( ) ?;
34
+ config_profiles. validate ( features, warnings) ?;
35
+
36
+ Ok ( Profiles {
30
37
dev : ProfileMaker {
31
38
default : Profile :: default_dev ( ) ,
32
- toml : dev,
39
+ toml : profiles. and_then ( |p| p. dev . clone ( ) ) ,
40
+ config : config_profiles. dev . clone ( ) ,
33
41
} ,
34
42
release : ProfileMaker {
35
43
default : Profile :: default_release ( ) ,
36
- toml : release,
44
+ toml : profiles. and_then ( |p| p. release . clone ( ) ) ,
45
+ config : config_profiles. release . clone ( ) ,
37
46
} ,
38
47
test : ProfileMaker {
39
48
default : Profile :: default_test ( ) ,
40
- toml : test,
49
+ toml : profiles. and_then ( |p| p. test . clone ( ) ) ,
50
+ config : None ,
41
51
} ,
42
52
bench : ProfileMaker {
43
53
default : Profile :: default_bench ( ) ,
44
- toml : bench,
54
+ toml : profiles. and_then ( |p| p. bench . clone ( ) ) ,
55
+ config : None ,
45
56
} ,
46
57
doc : ProfileMaker {
47
58
default : Profile :: default_doc ( ) ,
48
- toml : doc,
59
+ toml : profiles. and_then ( |p| p. doc . clone ( ) ) ,
60
+ config : None ,
49
61
} ,
50
- }
62
+ } )
51
63
}
52
64
53
65
/// Retrieve the profile for a target.
@@ -86,7 +98,7 @@ impl Profiles {
86
98
CompileMode :: Bench => & self . bench ,
87
99
CompileMode :: Doc { .. } => & self . doc ,
88
100
} ;
89
- let mut profile = maker. profile_for ( Some ( pkg_id) , is_member, profile_for) ;
101
+ let mut profile = maker. get_profile ( Some ( pkg_id) , is_member, profile_for) ;
90
102
// `panic` should not be set for tests/benches, or any of their
91
103
// dependencies.
92
104
if profile_for == ProfileFor :: TestDependency || mode. is_any_test ( ) {
@@ -112,9 +124,9 @@ impl Profiles {
112
124
/// select for the package that was actually built.
113
125
pub fn base_profile ( & self , release : bool ) -> Profile {
114
126
if release {
115
- self . release . profile_for ( None , true , ProfileFor :: Any )
127
+ self . release . get_profile ( None , true , ProfileFor :: Any )
116
128
} else {
117
- self . dev . profile_for ( None , true , ProfileFor :: Any )
129
+ self . dev . get_profile ( None , true , ProfileFor :: Any )
118
130
}
119
131
}
120
132
@@ -132,6 +144,7 @@ impl Profiles {
132
144
/// An object used for handling the profile override hierarchy.
133
145
///
134
146
/// The precedence of profiles are (first one wins):
147
+ /// - Profiles in .cargo/config files (using same order as below).
135
148
/// - [profile.dev.overrides.name] - A named package.
136
149
/// - [profile.dev.overrides."*"] - This cannot apply to workspace members.
137
150
/// - [profile.dev.build-override] - This can only apply to `build.rs` scripts
@@ -140,60 +153,45 @@ impl Profiles {
140
153
/// - Default (hard-coded) values.
141
154
#[ derive( Debug , Clone ) ]
142
155
struct ProfileMaker {
156
+ /// The starting, hard-coded defaults for the profile.
143
157
default : Profile ,
158
+ /// The profile from the `Cargo.toml` manifest.
144
159
toml : Option < TomlProfile > ,
160
+ /// Profile loaded from `.cargo/config` files.
161
+ config : Option < TomlProfile > ,
145
162
}
146
163
147
164
impl ProfileMaker {
148
- fn profile_for (
165
+ fn get_profile (
149
166
& self ,
150
167
pkg_id : Option < & PackageId > ,
151
168
is_member : bool ,
152
169
profile_for : ProfileFor ,
153
170
) -> Profile {
154
171
let mut profile = self . default ;
155
172
if let Some ( ref toml) = self . toml {
156
- merge_profile ( & mut profile, toml) ;
157
- if profile_for == ProfileFor :: CustomBuild {
158
- if let Some ( ref build_override) = toml. build_override {
159
- merge_profile ( & mut profile, build_override) ;
160
- }
161
- }
162
- if let Some ( ref overrides) = toml. overrides {
163
- if !is_member {
164
- if let Some ( all) = overrides. get ( & ProfilePackageSpec :: All ) {
165
- merge_profile ( & mut profile, all) ;
166
- }
167
- }
168
- if let Some ( pkg_id) = pkg_id {
169
- let mut matches = overrides. iter ( ) . filter_map (
170
- |( key, spec_profile) | match key {
171
- & ProfilePackageSpec :: All => None ,
172
- & ProfilePackageSpec :: Spec ( ref s) => if s. matches ( pkg_id) {
173
- Some ( spec_profile)
174
- } else {
175
- None
176
- } ,
177
- } ,
178
- ) ;
179
- if let Some ( spec_profile) = matches. next ( ) {
180
- merge_profile ( & mut profile, spec_profile) ;
181
- // `validate_packages` should ensure that there are
182
- // no additional matches.
183
- assert ! (
184
- matches. next( ) . is_none( ) ,
185
- "package `{}` matched multiple profile overrides" ,
186
- pkg_id
187
- ) ;
188
- }
189
- }
190
- }
173
+ merge_toml ( pkg_id, is_member, profile_for, & mut profile, toml) ;
174
+ }
175
+ if let Some ( ref toml) = self . config {
176
+ merge_toml ( pkg_id, is_member, profile_for, & mut profile, toml) ;
191
177
}
192
178
profile
193
179
}
194
180
195
181
fn validate_packages ( & self , shell : & mut Shell , packages : & PackageSet ) -> CargoResult < ( ) > {
196
- let toml = match self . toml {
182
+ self . validate_packages_toml ( shell, packages, & self . toml , true ) ?;
183
+ self . validate_packages_toml ( shell, packages, & self . config , false ) ?;
184
+ Ok ( ( ) )
185
+ }
186
+
187
+ fn validate_packages_toml (
188
+ & self ,
189
+ shell : & mut Shell ,
190
+ packages : & PackageSet ,
191
+ toml : & Option < TomlProfile > ,
192
+ warn_unmatched : bool ,
193
+ ) -> CargoResult < ( ) > {
194
+ let toml = match * toml {
197
195
Some ( ref toml) => toml,
198
196
None => return Ok ( ( ) ) ,
199
197
} ;
@@ -206,9 +204,9 @@ impl ProfileMaker {
206
204
for pkg_id in packages. package_ids ( ) {
207
205
let matches: Vec < & PackageIdSpec > = overrides
208
206
. keys ( )
209
- . filter_map ( |key| match key {
210
- & ProfilePackageSpec :: All => None ,
211
- & ProfilePackageSpec :: Spec ( ref spec) => if spec. matches ( pkg_id) {
207
+ . filter_map ( |key| match * key {
208
+ ProfilePackageSpec :: All => None ,
209
+ ProfilePackageSpec :: Spec ( ref spec) => if spec. matches ( pkg_id) {
212
210
Some ( spec)
213
211
} else {
214
212
None
@@ -237,9 +235,12 @@ impl ProfileMaker {
237
235
}
238
236
}
239
237
238
+ if !warn_unmatched {
239
+ return Ok ( ( ) ) ;
240
+ }
240
241
// Verify every override matches at least one package.
241
242
let missing_specs = overrides. keys ( ) . filter_map ( |key| {
242
- if let & ProfilePackageSpec :: Spec ( ref spec) = key {
243
+ if let ProfilePackageSpec :: Spec ( ref spec) = * key {
243
244
if !found. contains ( spec) {
244
245
return Some ( spec) ;
245
246
}
@@ -258,7 +259,7 @@ impl ProfileMaker {
258
259
}
259
260
} )
260
261
. collect ( ) ;
261
- if name_matches. len ( ) == 0 {
262
+ if name_matches. is_empty ( ) {
262
263
let suggestion = packages
263
264
. package_ids ( )
264
265
. map ( |p| ( lev_distance ( spec. name ( ) , & p. name ( ) ) , p. name ( ) ) )
@@ -289,6 +290,50 @@ impl ProfileMaker {
289
290
}
290
291
}
291
292
293
+ fn merge_toml (
294
+ pkg_id : Option < & PackageId > ,
295
+ is_member : bool ,
296
+ profile_for : ProfileFor ,
297
+ profile : & mut Profile ,
298
+ toml : & TomlProfile ,
299
+ ) {
300
+ merge_profile ( profile, toml) ;
301
+ if profile_for == ProfileFor :: CustomBuild {
302
+ if let Some ( ref build_override) = toml. build_override {
303
+ merge_profile ( profile, build_override) ;
304
+ }
305
+ }
306
+ if let Some ( ref overrides) = toml. overrides {
307
+ if !is_member {
308
+ if let Some ( all) = overrides. get ( & ProfilePackageSpec :: All ) {
309
+ merge_profile ( profile, all) ;
310
+ }
311
+ }
312
+ if let Some ( pkg_id) = pkg_id {
313
+ let mut matches = overrides
314
+ . iter ( )
315
+ . filter_map ( |( key, spec_profile) | match * key {
316
+ ProfilePackageSpec :: All => None ,
317
+ ProfilePackageSpec :: Spec ( ref s) => if s. matches ( pkg_id) {
318
+ Some ( spec_profile)
319
+ } else {
320
+ None
321
+ } ,
322
+ } ) ;
323
+ if let Some ( spec_profile) = matches. next ( ) {
324
+ merge_profile ( profile, spec_profile) ;
325
+ // `validate_packages` should ensure that there are
326
+ // no additional matches.
327
+ assert ! (
328
+ matches. next( ) . is_none( ) ,
329
+ "package `{}` matched multiple profile overrides" ,
330
+ pkg_id
331
+ ) ;
332
+ }
333
+ }
334
+ }
335
+ }
336
+
292
337
fn merge_profile ( profile : & mut Profile , toml : & TomlProfile ) {
293
338
if let Some ( ref opt_level) = toml. opt_level {
294
339
profile. opt_level = InternedString :: new ( & opt_level. 0 ) ;
@@ -483,3 +528,26 @@ impl ProfileFor {
483
528
& ALL
484
529
}
485
530
}
531
+
532
+ /// Profiles loaded from .cargo/config files.
533
+ #[ derive( Clone , Debug , Deserialize , Default ) ]
534
+ pub struct ConfigProfiles {
535
+ dev : Option < TomlProfile > ,
536
+ release : Option < TomlProfile > ,
537
+ }
538
+
539
+ impl ConfigProfiles {
540
+ pub fn validate ( & self , features : & Features , warnings : & mut Vec < String > ) -> CargoResult < ( ) > {
541
+ if let Some ( ref profile) = self . dev {
542
+ profile
543
+ . validate ( "dev" , features, warnings)
544
+ . chain_err ( || format_err ! ( "config profile `profile.dev` is not valid" ) ) ?;
545
+ }
546
+ if let Some ( ref profile) = self . release {
547
+ profile
548
+ . validate ( "release" , features, warnings)
549
+ . chain_err ( || format_err ! ( "config profile `profile.release` is not valid" ) ) ?;
550
+ }
551
+ Ok ( ( ) )
552
+ }
553
+ }
0 commit comments