diff --git a/easybuild/easyblocks/c/clang_aomp.py b/easybuild/easyblocks/c/clang_aomp.py index 0221c6c5a8..7237eac9c2 100644 --- a/easybuild/easyblocks/c/clang_aomp.py +++ b/easybuild/easyblocks/c/clang_aomp.py @@ -145,7 +145,7 @@ def configure_step(self): raise EasyBuildError("Could not find 'ROCm-Device-Libs' source directory in %s", self.builddir) num_comps = len(self.cfg['components']) - for idx, comp in enumerate(self.comp_cfgs): + for idx, (comp, _) in enumerate(self.comp_instances): name = comp['name'] msg = "configuring bundle component %s %s (%d/%d)..." % (name, comp['version'], idx + 1, num_comps) print_msg(msg) diff --git a/easybuild/easyblocks/generic/bundle.py b/easybuild/easyblocks/generic/bundle.py index 196b0e5f8b..4e1d9e9d3f 100644 --- a/easybuild/easyblocks/generic/bundle.py +++ b/easybuild/easyblocks/generic/bundle.py @@ -31,6 +31,7 @@ @author: Pieter De Baets (Ghent University) @author: Jens Timmerman (Ghent University) @author: Jasper Grimm (University of York) +@author: Jan Andre Reuter (Juelich Supercomputing Centre) """ import copy import os @@ -70,8 +71,8 @@ def __init__(self, *args, **kwargs): self.altroot = None self.altversion = None - # list of EasyConfig instances for components - self.comp_cfgs = [] + # list of EasyConfig instances and their EasyBlocks for components + self.comp_instances = [] # list of EasyConfig instances of components for which to run sanity checks self.comp_cfgs_sanity_check = [] @@ -207,7 +208,7 @@ def __init__(self, *args, **kwargs): comp_cfg.expect_resolved_template_values = True - self.comp_cfgs.append(comp_cfg) + self.comp_instances.append((comp_cfg, comp_cfg.easyblock(comp_cfg, logfile=self.logfile))) self.cfg.update('checksums', checksums_patches) @@ -226,7 +227,7 @@ def check_checksums(self): """ checksum_issues = super(Bundle, self).check_checksums() - for comp in self.comp_cfgs: + for comp, _ in self.comp_instances: checksum_issues.extend(self.check_checksums_for(comp, sub="of component %s" % comp['name'])) return checksum_issues @@ -256,14 +257,12 @@ def build_step(self): def install_step(self): """Install components, if specified.""" comp_cnt = len(self.cfg['components']) - for idx, cfg in enumerate(self.comp_cfgs): + for idx, (cfg, comp) in enumerate(self.comp_instances): print_msg("installing bundle component %s v%s (%d/%d)..." % (cfg['name'], cfg['version'], idx + 1, comp_cnt)) self.log.info("Installing component %s v%s using easyblock %s", cfg['name'], cfg['version'], cfg.easyblock) - comp = cfg.easyblock(cfg) - # correct build/install dirs comp.builddir = self.builddir comp.install_subdir, comp.installdir = self.install_subdir, self.installdir @@ -332,8 +331,40 @@ def install_step(self): new_val = path env.setvar(envvar, new_val) - # close log for this component - comp.close_log() + def make_module_req_guess(self): + """ + Set module requirements from all components, e.g. $PATH, etc. + During the install step, we only set these requirements temporarily. + Later on when building the module, those paths are not considered. + Therefore, iterate through all the components again and gather + the requirements. + + Do not remove duplicates or check for existence of folders, + as this is done in the generic EasyBlock while creating + the module file already. + """ + # Start with the paths from the generic EasyBlock. + # If not added here, they might be missing entirely and fail sanity checks. + final_reqs = super(Bundle, self).make_module_req_guess() + + for cfg, comp in self.comp_instances: + self.log.info("Gathering module paths for component %s v%s", cfg['name'], cfg['version']) + reqs = comp.make_module_req_guess() + + # Try-except block to fail with an easily understandable error message. + # This should only trigger when an EasyBlock returns non-dict module requirements + # for make_module_req_guess() which should then be fixed in the components EasyBlock. + try: + for key, value in sorted(reqs.items()): + if isinstance(value, str): + value = [value] + final_reqs.setdefault(key, []) + final_reqs[key].extend(value) + except AttributeError: + raise EasyBuildError("Cannot process module requirements of bundle component %s v%s", + cfg['name'], cfg['version']) + + return final_reqs def make_module_extra(self, *args, **kwargs): """Set extra stuff in module file, e.g. $EBROOT*, $EBVERSION*, etc.""" diff --git a/easybuild/easyblocks/q/quantumespresso.py b/easybuild/easyblocks/q/quantumespresso.py index eacad2a994..64c4cee5d1 100644 --- a/easybuild/easyblocks/q/quantumespresso.py +++ b/easybuild/easyblocks/q/quantumespresso.py @@ -28,6 +28,7 @@ @author: Kenneth Hoste (Ghent University) @author: Ake Sandgren (HPC2N, Umea University) @author: Davide Grassano (CECAM, EPFL) +@author: Jan Reuter (Juelich Supercomputing Centre) """ import fileinput @@ -84,6 +85,8 @@ def __init__(self, ec, *args, **kwargs): # Required to avoid CMakeMake default extra_opts to override the ConfigMake ones new_ec = EasyConfig(ec.path, extra_options=eb.extra_options()) + # Disable log file for nested EasyBlock + kwargs['logfile'] = self.logfile self.ebclass = eb(new_ec, *args, **kwargs) class EB_QuantumESPRESSOcmake(CMakeMake):