Skip to content

Commit 5524e2e

Browse files
committed
Make matching component sources in Bundle easyblock more reliable
Store where sources have been added to get the corresponding filled structure without relying on partially resolved templates.
1 parent bcdeb6d commit 5524e2e

1 file changed

Lines changed: 39 additions & 48 deletions

File tree

easybuild/easyblocks/generic/bundle.py

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)