@@ -57,11 +57,11 @@ pub enum Package {
5757pub struct Metadata {
5858 example_path : PathBuf ,
5959 chips : Vec < Chip > ,
60- feature_sets : Vec < Vec < String > > ,
60+ feature_set : Vec < String > ,
6161}
6262
6363impl Metadata {
64- pub fn new ( example_path : & Path , chips : Vec < Chip > , feature_sets : Vec < Vec < String > > ) -> Self {
64+ pub fn new ( example_path : & Path , chips : Vec < Chip > , feature_set : Vec < String > ) -> Self {
6565 let chips = if chips. is_empty ( ) {
6666 Chip :: iter ( ) . collect ( )
6767 } else {
@@ -71,7 +71,7 @@ impl Metadata {
7171 Self {
7272 example_path : example_path. to_path_buf ( ) ,
7373 chips,
74- feature_sets ,
74+ feature_set ,
7575 }
7676 }
7777
@@ -89,9 +89,9 @@ impl Metadata {
8989 . replace ( ".rs" , "" )
9090 }
9191
92- /// A list of all features required for building a given examples .
93- pub fn feature_sets ( & self ) -> & [ Vec < String > ] {
94- & self . feature_sets
92+ /// A list of all features required for building a given example .
93+ pub fn feature_set ( & self ) -> & [ String ] {
94+ & self . feature_set
9595 }
9696
9797 /// If the specified chip is in the list of chips, then it is supported.
@@ -154,7 +154,7 @@ pub fn build_documentation(
154154}
155155
156156/// Load all examples at the given path, and parse their metadata.
157- pub fn load_examples ( path : & Path ) -> Result < Vec < Metadata > > {
157+ pub fn load_examples ( path : & Path , action : CargoAction ) -> Result < Vec < Metadata > > {
158158 let mut examples = Vec :: new ( ) ;
159159
160160 for entry in fs:: read_dir ( path) ? {
@@ -172,7 +172,7 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
172172 . trim ( )
173173 . split_ascii_whitespace ( )
174174 . map ( |s| s. to_string ( ) )
175- . collect :: < VecDeque < _ > > ( ) ;
175+ . collect :: < Vec < _ > > ( ) ;
176176
177177 if split. len ( ) < 2 {
178178 bail ! (
@@ -182,7 +182,7 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
182182 }
183183
184184 // The trailing ':' on metadata keys is optional :)
185- let key = split. pop_front ( ) . unwrap ( ) ;
185+ let key = split. swap_remove ( 0 ) ;
186186 let key = key. trim_end_matches ( ':' ) ;
187187
188188 if key == "CHIPS" {
@@ -191,15 +191,31 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
191191 . map ( |s| Chip :: from_str ( s, false ) . unwrap ( ) )
192192 . collect :: < Vec < _ > > ( ) ;
193193 } else if key == "FEATURES" {
194- feature_sets. push ( split. into ( ) ) ;
194+ // Sort the features so they are in a deterministic order:
195+ split. sort ( ) ;
196+ feature_sets. push ( split) ;
195197 } else {
196198 log:: warn!( "Unrecognized metadata key '{key}', ignoring" ) ;
197199 }
198200 }
199201
200- examples. push ( Metadata :: new ( & path, chips, feature_sets) ) ;
202+ if feature_sets. is_empty ( ) {
203+ feature_sets. push ( Vec :: new ( ) ) ;
204+ }
205+ if action == CargoAction :: Build {
206+ // Only build the first feature set for each example.
207+ // Rebuilding with a different feature set just wastes time because the latter
208+ // one will overwrite the former one(s).
209+ feature_sets. truncate ( 1 ) ;
210+ }
211+ for feature_set in feature_sets {
212+ examples. push ( Metadata :: new ( & path, chips. clone ( ) , feature_set) ) ;
213+ }
201214 }
202215
216+ // Sort by feature set, to prevent rebuilding packages if not necessary.
217+ examples. sort_by_key ( |e| e. feature_set ( ) . join ( "," ) ) ;
218+
203219 Ok ( examples)
204220}
205221
@@ -210,38 +226,16 @@ pub fn execute_app(
210226 target : & str ,
211227 app : & Metadata ,
212228 action : CargoAction ,
213- repeat : usize ,
229+ mut repeat : usize ,
230+ debug : bool ,
214231) -> Result < ( ) > {
215232 log:: info!(
216233 "Building example '{}' for '{}'" ,
217234 app. example_path( ) . display( ) ,
218235 chip
219236 ) ;
220237
221- let feature_sets = if app. feature_sets ( ) . is_empty ( ) {
222- vec ! [ vec![ ] ]
223- } else {
224- app. feature_sets ( ) . to_vec ( )
225- } ;
226-
227- for features in feature_sets {
228- execute_app_with_features ( package_path, chip, target, app, action, repeat, features) ?;
229- }
230-
231- Ok ( ( ) )
232- }
233-
234- /// Run or build the specified test or example for the specified chip, with the
235- /// specified features enabled.
236- pub fn execute_app_with_features (
237- package_path : & Path ,
238- chip : Chip ,
239- target : & str ,
240- app : & Metadata ,
241- action : CargoAction ,
242- mut repeat : usize ,
243- mut features : Vec < String > ,
244- ) -> Result < ( ) > {
238+ let mut features = app. feature_set ( ) . to_vec ( ) ;
245239 if !features. is_empty ( ) {
246240 log:: info!( "Features: {}" , features. join( "," ) ) ;
247241 }
@@ -269,19 +263,22 @@ pub fn execute_app_with_features(
269263
270264 let mut builder = CargoArgsBuilder :: default ( )
271265 . subcommand ( subcommand)
272- . arg ( "--release" )
273266 . target ( target)
274267 . features ( & features)
275268 . arg ( bin) ;
276269
270+ if !debug {
271+ builder. add_arg ( "--release" ) ;
272+ }
273+
277274 if subcommand == "test" && chip == Chip :: Esp32c2 {
278- builder = builder . arg ( "--" ) . arg ( "--speed" ) . arg ( "15000" ) ;
275+ builder. add_arg ( "--" ) . add_arg ( "--speed" ) . add_arg ( "15000" ) ;
279276 }
280277
281278 // If targeting an Xtensa device, we must use the '+esp' toolchain modifier:
282279 if target. starts_with ( "xtensa" ) {
283280 builder = builder. toolchain ( "esp" ) ;
284- builder = builder . arg ( "-Zbuild-std=core,alloc" )
281+ builder. add_arg ( "-Zbuild-std=core,alloc" ) ;
285282 }
286283
287284 let args = builder. build ( ) ;
0 commit comments