@@ -105,6 +105,10 @@ def __init__(self, *args, **kwargs):
105105 # (like adding component sources to top-level sources easyconfig parameter)
106106 self .cfg = self .cfg .copy ()
107107
108+ # Keep track of sources for each component to restore them:
109+ # (Component instance, start idx [in self.src], end idx)
110+ self .comp_to_src_idxs = []
111+
108112 # disable templating to avoid premature resolving of template values
109113 # Note that self.cfg.update also resolves templates!
110114 with self .cfg .disable_templating ():
@@ -197,6 +201,10 @@ def __init__(self, *args, **kwargs):
197201
198202 comp_cfg .generate_template_values ()
199203
204+ # Combine all component sources into the top-level sources parameter
205+ # This allows reusing top-level source_urls and unpacking them all in the extract_step
206+
207+ old_num_srcs = len (self .cfg .get ('sources' , resolve = False ))
200208 # Don't require that all template values can be resolved at this point but still resolve them.
201209 # This is important to ensure that template values like %(name)s and %(version)s
202210 # are correctly resolved with the component name/version before values are copied over to self.cfg
@@ -226,21 +234,9 @@ def __init__(self, *args, **kwargs):
226234 comp_checksums = comp_cfg ['checksums' ]
227235 if comp_checksums :
228236 src_cnt = len (comp_sources )
229-
230237 # add per-component checksums for sources to list of checksums
231238 self .cfg .update ('checksums' , comp_checksums [:src_cnt ])
232239
233- # add per-component checksums for patches to list of checksums for patches
234- checksums_patches .extend (comp_checksums [src_cnt :])
235-
236- with comp_cfg .allow_unresolved_templates ():
237- comp_patches = comp_cfg ['patches' ]
238- comp_postinstall_patches = comp_cfg ['postinstallpatches' ]
239- if comp_patches :
240- self .cfg .update ('patches' , comp_patches )
241- # Patch step is skipped so adding postinstall patches of components here is harmless
242- self .cfg .update ('patches' , comp_postinstall_patches )
243-
244240 # instantiate the component to transfer further information
245241 comp_instance = comp_cfg .easyblock (comp_cfg , logfile = self .logfile )
246242
@@ -253,6 +249,11 @@ def __init__(self, *args, **kwargs):
253249 self .comp_cfgs_sanity_check .append (comp_instance )
254250 # lastly, add it to the list of components we'll deal with later
255251 self .comp_instances .append ((comp_cfg , comp_instance ))
252+ new_num_srcs = len (self .cfg .get ('sources' , resolve = False ))
253+ self .comp_to_src_idxs .append ((self .comp_instances [- 1 ], old_num_srcs , new_num_srcs ))
254+ # check if sanity checks are enabled for the component
255+ if self .cfg ['sanity_check_all_components' ] or comp_cfg ['name' ] in self .cfg ['sanity_check_components' ]:
256+ self .comp_cfgs_sanity_check .append (self .comp_instances [- 1 ])
256257
257258 self .cfg .update ('checksums' , checksums_patches + orig_checksums )
258259
@@ -274,14 +275,29 @@ def check_checksums(self):
274275
275276 return checksum_issues
276277
278+ def fetch_step (self ):
279+ """Fetch sources of all extensions"""
280+ super ().fetch_step ()
281+ # Init src attribute as usually done by fetch_step
282+ for (_ , comp ), start_idx , end_idx in self .comp_to_src_idxs :
283+ comp .src = self .src [start_idx :end_idx ]
284+ # need to run fetch_patches to ensure per-component patches are gathered
285+ comp .fetch_patches ()
286+
277287 def prepare_step (self , * args , ** kwargs ):
278288 """
279289 Pre-configure step.
280- At this point, dependencies are known. So transfer them to all components.
290+ At this point, dependencies & properties are known. So transfer them to all components.
281291 """
282- super ().prepare_step (self , * args , ** kwargs )
292+ super ().prepare_step (* args , ** kwargs )
283293 for _ , comp in self .comp_instances :
284294 comp .toolchain .dependencies = self .toolchain .dependencies
295+ # correct build/install dirs
296+ comp .builddir = self .builddir
297+ comp .install_subdir , comp .installdir = self .install_subdir , self .installdir
298+
299+ # make sure we can build in parallel
300+ comp .set_parallel ()
285301
286302 def patch_step (self ):
287303 """Patch step must be a no-op for bundle, since there are no top-level sources/patches."""
@@ -339,43 +355,18 @@ def install_step(self):
339355 (comp .name , comp .version , idx + 1 , comp_cnt ))
340356 self .log .info ("Installing component %s v%s using easyblock %s" , comp .name , comp .version , cfg .easyblock )
341357
342- # make sure we can build in parallel
343- comp .set_parallel ()
344-
358+ (??) # make sure we can build in parallel
359+ (??) comp .set_parallel ()
360+ (??)
345361 # figure out correct start directory
346- comp .guess_start_dir ()
347-
348- # need to run fetch_patches to ensure per-component patches are applied
349- comp .fetch_patches ()
350-
362+ # Compatibility with ECs expecting the previous behavior where src wasn't populated at this point
363+ tmp_src = comp .src
351364 comp .src = []
365+ comp .guess_start_dir ()
366+ comp .src = tmp_src
352367
353- # find matching entries in self.src for this component
354- with comp .cfg .allow_unresolved_templates ():
355- comp_sources = comp .cfg ['sources' ]
356- for source in comp_sources :
357- if isinstance (source , str ):
358- comp_src_fn = source
359- elif isinstance (source , dict ):
360- if 'filename' in source :
361- comp_src_fn = source ['filename' ]
362- else :
363- raise EasyBuildError ("Encountered source file specified as dict without 'filename': %s" , source )
364- else :
365- raise EasyBuildError ("Specification of unknown type for source file: %s" , source )
366-
367- found = False
368- for src in self .src :
369- if src ['name' ] == comp_src_fn :
370- self .log .info ("Found spec for source %s for component %s: %s" , comp_src_fn , comp .name , src )
371- comp .src .append (src )
372- found = True
373- break
374- if not found :
375- raise EasyBuildError ("Failed to find spec for source %s for component %s" , comp_src_fn , comp .name )
376-
377- # location of first unpacked source is used to determine where to apply patch(es)
378- comp .src [- 1 ]['finalpath' ] = comp .cfg ['start_dir' ]
368+ # location of first unpacked source is used to determine where to apply patch(es)
369+ comp .src [0 ]['finalpath' ] = comp .cfg ['start_dir' ]
379370
380371 self ._install_component (comp )
381372
0 commit comments