@@ -92,6 +92,8 @@ def __init__(self, *args, **kwargs):
92
92
# (like adding component sources to top-level sources easyconfig parameter)
93
93
self .cfg = self .cfg .copy ()
94
94
95
+ self .comp_to_src_idxs = []
96
+
95
97
# disable templating to avoid premature resolving of template values
96
98
# Note that self.cfg.update also resolves templates!
97
99
with self .cfg .disable_templating ():
@@ -166,6 +168,11 @@ def __init__(self, *args, **kwargs):
166
168
for key in comp_specs :
167
169
comp_cfg [key ] = comp_specs [key ]
168
170
171
+ # Combine all component sources into the top-level sources parameter
172
+ # This allows reusing top-level source_urls and unpacking them all in the extract_step
173
+
174
+ # Keep track of sources for each component to restore them: (Component instance, start idx [in self.src], end idx)
175
+ old_num_srcs = len (self .cfg .get ('sources' , resolve = False ))
169
176
# Don't require that all template values can be resolved at this point but still resolve them.
170
177
# This is important to ensure that template values like %(name)s and %(version)s
171
178
# are correctly resolved with the component name/version before values are copied over to self.cfg
@@ -195,19 +202,15 @@ def __init__(self, *args, **kwargs):
195
202
comp_checksums = comp_cfg ['checksums' ]
196
203
if comp_checksums :
197
204
src_cnt = len (comp_sources )
198
-
199
205
# add per-component checksums for sources to list of checksums
200
206
self .cfg .update ('checksums' , comp_checksums [:src_cnt ])
201
207
202
- # add per-component checksums for patches to list of checksums for patches
203
- checksums_patches .extend (comp_checksums [src_cnt :])
204
-
205
- with comp_cfg .allow_unresolved_templates ():
206
- comp_patches = comp_cfg ['patches' ]
207
- if comp_patches :
208
- self .cfg .update ('patches' , comp_patches )
209
-
210
208
self .comp_instances .append ((comp_cfg , comp_cfg .easyblock (comp_cfg , logfile = self .logfile )))
209
+ new_num_srcs = len (self .cfg .get ('sources' , resolve = False ))
210
+ self .comp_to_src_idxs .append ((self .comp_instances [- 1 ], old_num_srcs , new_num_srcs ))
211
+ # check if sanity checks are enabled for the component
212
+ if self .cfg ['sanity_check_all_components' ] or comp_cfg ['name' ] in self .cfg ['sanity_check_components' ]:
213
+ self .comp_cfgs_sanity_check .append (self .comp_instances [- 1 ])
211
214
212
215
self .cfg .update ('checksums' , checksums_patches )
213
216
@@ -229,6 +232,26 @@ def check_checksums(self):
229
232
230
233
return checksum_issues
231
234
235
+ def fetch_step (self ):
236
+ """Fetch sources of all extensions"""
237
+ super ().fetch_step ()
238
+ # Init src attribute as usually done by fetch_step
239
+ for (_ , comp ), start_idx , end_idx in self .comp_to_src_idxs :
240
+ comp .src = self .src [start_idx :end_idx ]
241
+ # need to run fetch_patches to ensure per-component patches are gathered
242
+ comp .fetch_patches ()
243
+
244
+ def prepare_step (self , * args , ** kwargs ):
245
+ """Init required properties for components"""
246
+ super ().prepare_step (* args , ** kwargs )
247
+ for _ , comp in self .comp_instances :
248
+ # correct build/install dirs
249
+ comp .builddir = self .builddir
250
+ comp .install_subdir , comp .installdir = self .install_subdir , self .installdir
251
+
252
+ # make sure we can build in parallel
253
+ comp .set_parallel ()
254
+
232
255
def patch_step (self ):
233
256
"""Patch step must be a no-op for bundle, since there are no top-level sources/patches."""
234
257
pass
@@ -260,47 +283,15 @@ def install_step(self):
260
283
(cfg ['name' ], cfg ['version' ], idx + 1 , comp_cnt ))
261
284
self .log .info ("Installing component %s v%s using easyblock %s" , cfg ['name' ], cfg ['version' ], cfg .easyblock )
262
285
263
- # correct build/install dirs
264
- comp .builddir = self .builddir
265
- comp .install_subdir , comp .installdir = self .install_subdir , self .installdir
266
-
267
- # make sure we can build in parallel
268
- comp .set_parallel ()
269
-
270
286
# figure out correct start directory
271
- comp .guess_start_dir ()
272
-
273
- # need to run fetch_patches to ensure per-component patches are applied
274
- comp .fetch_patches ()
275
-
287
+ # Compatibility with ECs expecting the previous behavior where src wasn't populated at this point
288
+ tmp_src = comp .src
276
289
comp .src = []
290
+ comp .guess_start_dir ()
291
+ comp .src = tmp_src
277
292
278
- # find matching entries in self.src for this component
279
- with comp .cfg .allow_unresolved_templates ():
280
- comp_sources = comp .cfg ['sources' ]
281
- for source in comp_sources :
282
- if isinstance (source , str ):
283
- comp_src_fn = source
284
- elif isinstance (source , dict ):
285
- if 'filename' in source :
286
- comp_src_fn = source ['filename' ]
287
- else :
288
- raise EasyBuildError ("Encountered source file specified as dict without 'filename': %s" , source )
289
- else :
290
- raise EasyBuildError ("Specification of unknown type for source file: %s" , source )
291
-
292
- found = False
293
- for src in self .src :
294
- if src ['name' ] == comp_src_fn :
295
- self .log .info ("Found spec for source %s for component %s: %s" , comp_src_fn , comp .name , src )
296
- comp .src .append (src )
297
- found = True
298
- break
299
- if not found :
300
- raise EasyBuildError ("Failed to find spec for source %s for component %s" , comp_src_fn , comp .name )
301
-
302
- # location of first unpacked source is used to determine where to apply patch(es)
303
- comp .src [- 1 ]['finalpath' ] = comp .cfg ['start_dir' ]
293
+ # location of first unpacked source is used to determine where to apply patch(es)
294
+ comp .src [0 ]['finalpath' ] = comp .cfg ['start_dir' ]
304
295
305
296
# check if sanity checks are enabled for the component
306
297
if self .cfg ['sanity_check_all_components' ] or comp .cfg ['name' ] in self .cfg ['sanity_check_components' ]:
0 commit comments