Skip to content

Commit 029d1f8

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 0e690d3 commit 029d1f8

File tree

1 file changed

+39
-50
lines changed

1 file changed

+39
-50
lines changed

easybuild/easyblocks/generic/bundle.py

Lines changed: 39 additions & 50 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,22 +234,15 @@ 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
self.comp_instances.append((comp_cfg, comp_cfg.easyblock(comp_cfg, logfile=self.logfile)))
241+
new_num_srcs = len(self.cfg.get('sources', resolve=False))
242+
self.comp_to_src_idxs.append((self.comp_instances[-1], old_num_srcs, new_num_srcs))
243+
# check if sanity checks are enabled for the component
244+
if self.cfg['sanity_check_all_components'] or comp_cfg['name'] in self.cfg['sanity_check_components']:
245+
self.comp_cfgs_sanity_check.append(self.comp_instances[-1])
245246

246247
self.cfg.update('checksums', checksums_patches + orig_checksums)
247248

@@ -263,6 +264,26 @@ def check_checksums(self):
263264

264265
return checksum_issues
265266

267+
def fetch_step(self):
268+
"""Fetch sources of all extensions"""
269+
super().fetch_step()
270+
# Init src attribute as usually done by fetch_step
271+
for (_, comp), start_idx, end_idx in self.comp_to_src_idxs:
272+
comp.src = self.src[start_idx:end_idx]
273+
# need to run fetch_patches to ensure per-component patches are gathered
274+
comp.fetch_patches()
275+
276+
def prepare_step(self, *args, **kwargs):
277+
"""Init required properties for components"""
278+
super().prepare_step(*args, **kwargs)
279+
for _, comp in self.comp_instances:
280+
# correct build/install dirs
281+
comp.builddir = self.builddir
282+
comp.install_subdir, comp.installdir = self.install_subdir, self.installdir
283+
284+
# make sure we can build in parallel
285+
comp.set_parallel()
286+
266287
def patch_step(self):
267288
"""Patch step must be a no-op for bundle, since there are no top-level sources/patches."""
268289
pass
@@ -319,47 +340,15 @@ def install_step(self):
319340
(comp.name, comp.version, idx + 1, comp_cnt))
320341
self.log.info("Installing component %s v%s using easyblock %s", comp.name, comp.version, cfg.easyblock)
321342

322-
# correct build/install dirs
323-
comp.builddir = self.builddir
324-
comp.install_subdir, comp.installdir = self.install_subdir, self.installdir
325-
326-
# make sure we can build in parallel
327-
comp.set_parallel()
328-
329343
# figure out correct start directory
330-
comp.guess_start_dir()
331-
332-
# need to run fetch_patches to ensure per-component patches are applied
333-
comp.fetch_patches()
334-
344+
# Compatibility with ECs expecting the previous behavior where src wasn't populated at this point
345+
tmp_src = comp.src
335346
comp.src = []
347+
comp.guess_start_dir()
348+
comp.src = tmp_src
336349

337-
# find matching entries in self.src for this component
338-
with comp.cfg.allow_unresolved_templates():
339-
comp_sources = comp.cfg['sources']
340-
for source in comp_sources:
341-
if isinstance(source, str):
342-
comp_src_fn = source
343-
elif isinstance(source, dict):
344-
if 'filename' in source:
345-
comp_src_fn = source['filename']
346-
else:
347-
raise EasyBuildError("Encountered source file specified as dict without 'filename': %s", source)
348-
else:
349-
raise EasyBuildError("Specification of unknown type for source file: %s", source)
350-
351-
found = False
352-
for src in self.src:
353-
if src['name'] == comp_src_fn:
354-
self.log.info("Found spec for source %s for component %s: %s", comp_src_fn, comp.name, src)
355-
comp.src.append(src)
356-
found = True
357-
break
358-
if not found:
359-
raise EasyBuildError("Failed to find spec for source %s for component %s", comp_src_fn, comp.name)
360-
361-
# location of first unpacked source is used to determine where to apply patch(es)
362-
comp.src[-1]['finalpath'] = comp.cfg['start_dir']
350+
# location of first unpacked source is used to determine where to apply patch(es)
351+
comp.src[0]['finalpath'] = comp.cfg['start_dir']
363352

364353
# check if sanity checks are enabled for the component
365354
if self.cfg['sanity_check_all_components'] or comp.name in self.cfg['sanity_check_components']:

0 commit comments

Comments
 (0)