1
1
use std:: collections:: HashSet ;
2
+ use std:: path:: Path ;
2
3
use std:: { cmp, env, fmt, hash} ;
3
4
4
5
use serde:: Deserialize ;
5
6
6
7
use crate :: core:: compiler:: CompileMode ;
7
8
use crate :: core:: interning:: InternedString ;
8
- use crate :: core:: { Features , PackageId , PackageIdSpec , PackageSet , Shell } ;
9
+ use crate :: core:: { Feature , Features , PackageId , PackageIdSpec , PackageSet , Shell } ;
9
10
use crate :: util:: errors:: CargoResultExt ;
10
11
use crate :: util:: lev_distance:: lev_distance;
11
12
use crate :: util:: toml:: { ProfilePackageSpec , StringOrBool , TomlProfile , TomlProfiles , U32OrBool } ;
@@ -19,10 +20,13 @@ pub struct Profiles {
19
20
test : ProfileMaker ,
20
21
bench : ProfileMaker ,
21
22
doc : ProfileMaker ,
23
+ build : ProfileMaker ,
22
24
/// Incremental compilation can be overridden globally via:
23
25
/// - `CARGO_INCREMENTAL` environment variable.
24
26
/// - `build.incremental` config value.
25
27
incremental : Option < bool > ,
28
+ // Temporary flag to detect if unstable feature is enabled.
29
+ build_enabled : bool ,
26
30
}
27
31
28
32
impl Profiles {
@@ -31,9 +35,13 @@ impl Profiles {
31
35
config : & Config ,
32
36
features : & Features ,
33
37
warnings : & mut Vec < String > ,
38
+ manifest_path : & Path ,
34
39
) -> CargoResult < Profiles > {
35
40
if let Some ( profiles) = profiles {
36
41
profiles. validate ( features, warnings) ?;
42
+ if profiles. build . is_some ( ) {
43
+ features. require ( Feature :: build_profile ( ) ) ?;
44
+ }
37
45
}
38
46
39
47
let config_profiles = config. profiles ( ) ?;
@@ -43,6 +51,18 @@ impl Profiles {
43
51
None => config. get :: < Option < bool > > ( "build.incremental" ) ?,
44
52
} ;
45
53
54
+ let config_build_profile =
55
+ if !features. is_enabled ( Feature :: build_profile ( ) ) && config_profiles. build . is_some ( ) {
56
+ warnings. push ( format ! (
57
+ "profile `build` in config file will be ignored for \
58
+ manifest `{}` because \" build-profile\" feature is not enabled",
59
+ manifest_path. display( )
60
+ ) ) ;
61
+ None
62
+ } else {
63
+ config_profiles. build . clone ( )
64
+ } ;
65
+
46
66
Ok ( Profiles {
47
67
dev : ProfileMaker {
48
68
default : Profile :: default_dev ( ) ,
@@ -69,7 +89,13 @@ impl Profiles {
69
89
toml : profiles. and_then ( |p| p. doc . clone ( ) ) ,
70
90
config : None ,
71
91
} ,
92
+ build : ProfileMaker {
93
+ default : Profile :: default_build ( ) ,
94
+ toml : profiles. and_then ( |p| p. build . clone ( ) ) ,
95
+ config : config_build_profile,
96
+ } ,
72
97
incremental,
98
+ build_enabled : features. is_enabled ( Feature :: build_profile ( ) ) ,
73
99
} )
74
100
}
75
101
@@ -100,10 +126,14 @@ impl Profiles {
100
126
// `build_unit_profiles` normally ensures that it selects the
101
127
// ancestor's profile. However, `cargo clean -p` can hit this
102
128
// path.
103
- if release {
104
- & self . release
129
+ let maker = if release { & self . release } else { & self . dev } ;
130
+ if ( unit_for. build )
131
+ && self . build_enabled
132
+ && !maker. has_build_override ( )
133
+ {
134
+ & self . build
105
135
} else {
106
- & self . dev
136
+ maker
107
137
}
108
138
}
109
139
CompileMode :: Doc { .. } => & self . doc ,
@@ -148,9 +178,11 @@ impl Profiles {
148
178
/// select for the package that was actually built.
149
179
pub fn base_profile ( & self , release : bool ) -> Profile {
150
180
if release {
151
- self . release . get_profile ( None , true , UnitFor :: new_normal ( ) )
181
+ self . release
182
+ . get_profile ( None , true , UnitFor :: new_normal ( ) )
152
183
} else {
153
- self . dev . get_profile ( None , true , UnitFor :: new_normal ( ) )
184
+ self . dev
185
+ . get_profile ( None , true , UnitFor :: new_normal ( ) )
154
186
}
155
187
}
156
188
@@ -165,6 +197,7 @@ impl Profiles {
165
197
self . test . validate_packages ( shell, packages) ?;
166
198
self . bench . validate_packages ( shell, packages) ?;
167
199
self . doc . validate_packages ( shell, packages) ?;
200
+ self . build . validate_packages ( shell, packages) ?;
168
201
Ok ( ( ) )
169
202
}
170
203
}
@@ -198,10 +231,22 @@ impl ProfileMaker {
198
231
) -> Profile {
199
232
let mut profile = self . default ;
200
233
if let Some ( ref toml) = self . toml {
201
- merge_toml ( pkg_id, is_member, unit_for, & mut profile, toml) ;
234
+ merge_toml (
235
+ pkg_id,
236
+ is_member,
237
+ unit_for,
238
+ & mut profile,
239
+ toml,
240
+ ) ;
202
241
}
203
242
if let Some ( ref toml) = self . config {
204
- merge_toml ( pkg_id, is_member, unit_for, & mut profile, toml) ;
243
+ merge_toml (
244
+ pkg_id,
245
+ is_member,
246
+ unit_for,
247
+ & mut profile,
248
+ toml,
249
+ ) ;
205
250
}
206
251
profile
207
252
}
@@ -318,6 +363,13 @@ impl ProfileMaker {
318
363
}
319
364
Ok ( ( ) )
320
365
}
366
+
367
+ fn has_build_override ( & self ) -> bool {
368
+ self . toml
369
+ . as_ref ( )
370
+ . map ( |tp| tp. build_override . is_some ( ) )
371
+ . unwrap_or ( false )
372
+ }
321
373
}
322
374
323
375
fn merge_toml (
@@ -449,6 +501,7 @@ compact_debug! {
449
501
"test" => ( Profile :: default_test( ) , "default_test()" ) ,
450
502
"bench" => ( Profile :: default_bench( ) , "default_bench()" ) ,
451
503
"doc" => ( Profile :: default_doc( ) , "default_doc()" ) ,
504
+ "build" => ( Profile :: default_build( ) , "default_build()" ) ,
452
505
_ => ( Profile :: default ( ) , "default()" ) ,
453
506
} ;
454
507
[ debug_the_fields(
@@ -529,6 +582,13 @@ impl Profile {
529
582
}
530
583
}
531
584
585
+ fn default_build ( ) -> Profile {
586
+ Profile {
587
+ name : "build" ,
588
+ ..Profile :: default ( )
589
+ }
590
+ }
591
+
532
592
/// Compares all fields except `name`, which doesn't affect compilation.
533
593
/// This is necessary for `Unit` deduplication for things like "test" and
534
594
/// "dev" which are essentially the same.
@@ -604,31 +664,33 @@ pub struct UnitFor {
604
664
impl UnitFor {
605
665
/// A unit for a normal target/dependency (i.e., not custom build,
606
666
/// proc macro/plugin, or test/bench).
607
- pub fn new_normal ( ) -> UnitFor {
667
+ pub const fn new_normal ( ) -> UnitFor {
608
668
UnitFor {
609
669
build : false ,
610
670
panic_abort_ok : true ,
611
671
}
612
672
}
613
673
614
674
/// A unit for a custom build script or its dependencies.
615
- pub fn new_build ( ) -> UnitFor {
675
+ pub const fn new_build ( ) -> UnitFor {
616
676
UnitFor {
617
677
build : true ,
618
678
panic_abort_ok : false ,
619
679
}
620
680
}
621
681
622
682
/// A unit for a proc macro or compiler plugin or their dependencies.
623
- pub fn new_compiler ( ) -> UnitFor {
683
+ pub const fn new_compiler ( ) -> UnitFor {
684
+ // Note: This is currently the same as `new_build`, but keeping it
685
+ // separate for now in case it is useful in the future.
624
686
UnitFor {
625
- build : false ,
687
+ build : true ,
626
688
panic_abort_ok : false ,
627
689
}
628
690
}
629
691
630
692
/// A unit for a test/bench target or their dependencies.
631
- pub fn new_test ( ) -> UnitFor {
693
+ pub const fn new_test ( ) -> UnitFor {
632
694
UnitFor {
633
695
build : false ,
634
696
panic_abort_ok : false ,
@@ -660,18 +722,9 @@ impl UnitFor {
660
722
/// All possible values, used by `clean`.
661
723
pub fn all_values ( ) -> & ' static [ UnitFor ] {
662
724
static ALL : [ UnitFor ; 3 ] = [
663
- UnitFor {
664
- build : false ,
665
- panic_abort_ok : true ,
666
- } ,
667
- UnitFor {
668
- build : true ,
669
- panic_abort_ok : false ,
670
- } ,
671
- UnitFor {
672
- build : false ,
673
- panic_abort_ok : false ,
674
- } ,
725
+ UnitFor :: new_normal ( ) ,
726
+ UnitFor :: new_build ( ) ,
727
+ UnitFor :: new_test ( ) ,
675
728
] ;
676
729
& ALL
677
730
}
@@ -682,22 +735,29 @@ impl UnitFor {
682
735
pub struct ConfigProfiles {
683
736
dev : Option < TomlProfile > ,
684
737
release : Option < TomlProfile > ,
738
+ build : Option < TomlProfile > ,
685
739
}
686
740
687
741
impl ConfigProfiles {
688
742
pub fn validate ( & self , features : & Features , warnings : & mut Vec < String > ) -> CargoResult < ( ) > {
689
- if let Some ( ref profile) = self . dev {
690
- profile
691
- . validate ( "dev" , features, warnings)
692
- . chain_err ( || failure:: format_err!( "config profile `profile.dev` is not valid" ) ) ?;
693
- }
694
- if let Some ( ref profile) = self . release {
695
- profile
696
- . validate ( "release" , features, warnings)
697
- . chain_err ( || {
698
- failure:: format_err!( "config profile `profile.release` is not valid" )
699
- } ) ?;
743
+ macro_rules! check_profile {
744
+ ( $name: ident) => {
745
+ if let Some ( ref profile) = self . $name {
746
+ profile
747
+ . validate( stringify!( $name) , features, warnings)
748
+ . chain_err( || {
749
+ failure:: format_err!(
750
+ "config profile `profile.{}` is not valid" ,
751
+ stringify!( $name)
752
+ )
753
+ } ) ?;
754
+ }
755
+ } ;
700
756
}
757
+
758
+ check_profile ! ( dev) ;
759
+ check_profile ! ( release) ;
760
+ check_profile ! ( build) ;
701
761
Ok ( ( ) )
702
762
}
703
763
}
0 commit comments