From a452f274cd308edb4e0b6c6094224ff4421ccd84 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Tue, 19 Nov 2024 01:53:41 +0100 Subject: [PATCH 01/10] replace make_module_req_guess with module_load_environment in PythonPackage easyblock --- easybuild/easyblocks/generic/pythonpackage.py | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/easybuild/easyblocks/generic/pythonpackage.py b/easybuild/easyblocks/generic/pythonpackage.py index f45cc6c8e16..7e02c232e8d 100644 --- a/easybuild/easyblocks/generic/pythonpackage.py +++ b/easybuild/easyblocks/generic/pythonpackage.py @@ -48,7 +48,7 @@ from easybuild.framework.easyconfig.templates import PYPI_SOURCE from easybuild.framework.extensioneasyblock import ExtensionEasyBlock from easybuild.tools.build_log import EasyBuildError, print_msg -from easybuild.tools.config import build_option, PYTHONPATH, EBPYTHONPREFIXES +from easybuild.tools.config import build_option, PYTHONPATH, EBPYTHONPREFIXES, SEARCH_PATH_LIB_DIRS from easybuild.tools.filetools import change_dir, mkdir, remove_dir, symlink, which from easybuild.tools.modules import get_software_root from easybuild.tools.run import run_shell_cmd, subprocess_popen_text @@ -1148,27 +1148,30 @@ def sanity_check_step(self, *args, **kwargs): return (parent_success and success, parent_fail_msg + fail_msg) - def make_module_req_guess(self): + def make_module_step(self, *args, **kwargs): """ - Define list of subdirectories to consider for updating path-like environment variables ($PATH, etc.). + Define list of subdirectories in search paths of module load environment """ - guesses = super(PythonPackage, self).make_module_req_guess() - # avoid that lib subdirs are appended to $*LIBRARY_PATH if they don't provide libraries # typically, only lib/pythonX.Y/site-packages should be added to $PYTHONPATH (see make_module_extra) - for envvar in ['LD_LIBRARY_PATH', 'LIBRARY_PATH']: - newlist = [] - for subdir in guesses[envvar]: + for env_var in ['LD_LIBRARY_PATH', 'LIBRARY_PATH']: + search_paths = getattr(self.module_load_environment, env_var) + for lib_dir in SEARCH_PATH_LIB_DIRS: # only subdirectories that contain one or more files/libraries should be retained - fullpath = os.path.join(self.installdir, subdir) - if os.path.exists(fullpath): - if any([os.path.isfile(os.path.join(fullpath, x)) for x in os.listdir(fullpath)]): - newlist.append(subdir) - self.log.debug("Only retaining %s subdirs from %s for $%s (others don't provide any libraries)", - newlist, guesses[envvar], envvar) - guesses[envvar] = newlist - - return guesses + install_lib_dir = os.path.join(self.installdir, lib_dir) + try: + lib_files = [os.path.isfile(os.path.join(install_lib_dir, x)) for x in os.listdir(install_lib_dir)] + except FileNotFoundError: + lib_files = [] + + if any(lib_files): + search_paths.append(lib_dir) + else: + search_paths.remove(lib_dir) + + self.log.debug(f"Directories retained in module load environment for ${env_var}: [{search_paths}]") + + return super().make_module_step(*args, **kwargs) def make_module_extra(self, *args, **kwargs): """Add install path to PYTHONPATH""" From 217dcfbe7d3e71866d17b607354fa9e832c33f45 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 22 Nov 2024 01:21:39 +0100 Subject: [PATCH 02/10] replace make_module_req_guess with module_load_environment in Bundle easyblock and ensure environment variables point to expanded existing paths --- easybuild/easyblocks/generic/bundle.py | 31 ++++++++++++++------------ 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/easybuild/easyblocks/generic/bundle.py b/easybuild/easyblocks/generic/bundle.py index 437cd707d46..71a6823c638 100644 --- a/easybuild/easyblocks/generic/bundle.py +++ b/easybuild/easyblocks/generic/bundle.py @@ -41,6 +41,7 @@ from easybuild.framework.easyconfig.easyconfig import get_easyblock_class from easybuild.tools.build_log import EasyBuildError, print_msg from easybuild.tools.modules import get_software_root, get_software_version +from easybuild.tools.utilities import nub class Bundle(EasyBlock): @@ -305,20 +306,22 @@ def install_step(self): else: comp.run_step(step_name, [lambda x: getattr(x, '%s_step' % step_name)]) - # update environment to ensure stuff provided by former components can be picked up by latter components - # once the installation is finalised, this is handled by the generated module - reqs = comp.make_module_req_guess() - for envvar in reqs: - curr_val = os.getenv(envvar, '') - curr_paths = curr_val.split(os.pathsep) - for subdir in reqs[envvar]: - path = os.path.join(self.installdir, subdir) - if path not in curr_paths: - if curr_val: - new_val = '%s:%s' % (path, curr_val) - else: - new_val = path - env.setvar(envvar, new_val) + # Update current environment with component environment to ensure stuff provided + # by this component can be picked up by installation of subsequent components + # - this is a stripped down version of EasyBlock.make_module_req for fake modules + # - once bundle installation is complete, this is handled by the generated module as usual + for mod_envar, mod_paths in comp.module_load_environment.items(): + # expand glob patterns in module load environment to existing absolute paths + mod_expand = [x for p in mod_paths for x in comp.expand_module_search_path(p, False, fake=True)] + mod_expand = nub(mod_expand) + mod_expand = [os.path.join(self.installdir, path) for path in mod_expand] + # prepend to current environment variable if new stuff added to installation + curr_env = os.getenv(mod_envar, '') + curr_paths = [path for path in curr_env.split(os.pathsep) if path] + new_paths = nub(mod_expand + curr_paths) + new_env = os.pathsep.join(new_paths) + if new_env and new_env != curr_env: + env.setvar(mod_envar, new_env) # close log for this component comp.close_log() From 0000f5dbe82fbb4ee24c79826e970a34f55ac306 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 22 Nov 2024 01:27:41 +0100 Subject: [PATCH 03/10] replace make_module_req_guess with module_load_environment in FlexiBLAS easyblock --- easybuild/easyblocks/f/flexiblas.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/f/flexiblas.py b/easybuild/easyblocks/f/flexiblas.py index b3d51293855..feee155280b 100644 --- a/easybuild/easyblocks/f/flexiblas.py +++ b/easybuild/easyblocks/f/flexiblas.py @@ -85,6 +85,9 @@ def __init__(self, *args, **kwargs): self.obj_builddir = os.path.join(self.builddir, 'easybuild_obj') + # custom CPATH to FlexiBLAS headers + self.module_load_environment.CPATH = [os.path.join('include', 'flexiblas')] + def configure_step(self): """Custom configuration for FlexiBLAS, based on which BLAS libraries are included as dependencies.""" @@ -223,12 +226,3 @@ def sanity_check_step(self): custom_commands.append("flexiblas list | grep %s" % blas_lib.upper()) super(EB_FlexiBLAS, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) - - def make_module_req_guess(self): - """Customize CPATH for FlexiBLAS.""" - - guesses = super(EB_FlexiBLAS, self).make_module_req_guess() - - guesses.update({'CPATH': [os.path.join('include', 'flexiblas')]}) - - return guesses From a820814735b5a468aab141e62c2e89b2f4871cb2 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 22 Nov 2024 13:56:40 +0100 Subject: [PATCH 04/10] hide get_major_perl_version and get_site_suffix commands from terminal in Perl easyblock --- easybuild/easyblocks/p/perl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/p/perl.py b/easybuild/easyblocks/p/perl.py index 159f7552730..de9fe301534 100644 --- a/easybuild/easyblocks/p/perl.py +++ b/easybuild/easyblocks/p/perl.py @@ -198,7 +198,7 @@ def get_major_perl_version(): Returns the major verson of the perl binary in the current path """ cmd = "perl -MConfig -e 'print $Config::Config{PERL_API_REVISION}'" - res = run_shell_cmd(cmd) + res = run_shell_cmd(cmd, hidden=True) return res.output @@ -212,7 +212,7 @@ def get_site_suffix(tag): """ perl_cmd = 'my $a = $Config::Config{"%s"}; $a =~ s/($Config::Config{"siteprefix"})//; print $a' % tag cmd = "perl -MConfig -e '%s'" % perl_cmd - res = run_shell_cmd(cmd) + res = run_shell_cmd(cmd, hidden=True) sitesuffix = res.output # obtained value usually contains leading '/', so strip it off return sitesuffix.lstrip(os.path.sep) From e019932ec18b578a98cfec8d7ce01a9ba9a64f94 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Fri, 22 Nov 2024 13:56:52 +0100 Subject: [PATCH 05/10] replace make_module_req_guess with module_load_environment in PerlModule easyblock --- easybuild/easyblocks/generic/perlmodule.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/easybuild/easyblocks/generic/perlmodule.py b/easybuild/easyblocks/generic/perlmodule.py index c3c537f299e..5ce96d05786 100644 --- a/easybuild/easyblocks/generic/perlmodule.py +++ b/easybuild/easyblocks/generic/perlmodule.py @@ -139,14 +139,15 @@ def sanity_check_step(self, *args, **kwargs): """ return ExtensionEasyBlock.sanity_check_step(self, EXTS_FILTER_PERL_MODULES, *args, **kwargs) - def make_module_req_guess(self): - """Customized dictionary of paths to look for with PERL*LIB.""" - majver = get_major_perl_version() + def make_module_step(self, *args, **kwargs): + """ + Custom paths to look for with PERL*LIB + """ + perl_lib_var = f"PERL{get_major_perl_version()}LIB" sitearchsuffix = get_site_suffix('sitearch') sitelibsuffix = get_site_suffix('sitelib') + setattr(self.module_load_environment, perl_lib_var, ['', sitearchsuffix, sitelibsuffix]) + self.log.debug(f"MODVAR: {perl_lib_var} - " + str(getattr(self.module_load_environment, perl_lib_var))) + + return super().make_module_step(*args, **kwargs) - guesses = super(PerlModule, self).make_module_req_guess() - guesses.update({ - "PERL%sLIB" % majver: ['', sitearchsuffix, sitelibsuffix], - }) - return guesses From f8c1e932c009edea990cd9abff47f2bddbd8c00e Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 11 Dec 2024 11:28:27 +0100 Subject: [PATCH 06/10] Revert "replace make_module_req_guess with module_load_environment in PerlModule easyblock" This reverts commit e019932ec18b578a98cfec8d7ce01a9ba9a64f94. --- easybuild/easyblocks/generic/perlmodule.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/easybuild/easyblocks/generic/perlmodule.py b/easybuild/easyblocks/generic/perlmodule.py index 5ce96d05786..c3c537f299e 100644 --- a/easybuild/easyblocks/generic/perlmodule.py +++ b/easybuild/easyblocks/generic/perlmodule.py @@ -139,15 +139,14 @@ def sanity_check_step(self, *args, **kwargs): """ return ExtensionEasyBlock.sanity_check_step(self, EXTS_FILTER_PERL_MODULES, *args, **kwargs) - def make_module_step(self, *args, **kwargs): - """ - Custom paths to look for with PERL*LIB - """ - perl_lib_var = f"PERL{get_major_perl_version()}LIB" + def make_module_req_guess(self): + """Customized dictionary of paths to look for with PERL*LIB.""" + majver = get_major_perl_version() sitearchsuffix = get_site_suffix('sitearch') sitelibsuffix = get_site_suffix('sitelib') - setattr(self.module_load_environment, perl_lib_var, ['', sitearchsuffix, sitelibsuffix]) - self.log.debug(f"MODVAR: {perl_lib_var} - " + str(getattr(self.module_load_environment, perl_lib_var))) - - return super().make_module_step(*args, **kwargs) + guesses = super(PerlModule, self).make_module_req_guess() + guesses.update({ + "PERL%sLIB" % majver: ['', sitearchsuffix, sitelibsuffix], + }) + return guesses From 71231049c621ac21397f049690fd3bffd70a9309 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 11 Dec 2024 11:28:34 +0100 Subject: [PATCH 07/10] Revert "hide get_major_perl_version and get_site_suffix commands from terminal in Perl easyblock" This reverts commit a820814735b5a468aab141e62c2e89b2f4871cb2. --- easybuild/easyblocks/p/perl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/easyblocks/p/perl.py b/easybuild/easyblocks/p/perl.py index de9fe301534..159f7552730 100644 --- a/easybuild/easyblocks/p/perl.py +++ b/easybuild/easyblocks/p/perl.py @@ -198,7 +198,7 @@ def get_major_perl_version(): Returns the major verson of the perl binary in the current path """ cmd = "perl -MConfig -e 'print $Config::Config{PERL_API_REVISION}'" - res = run_shell_cmd(cmd, hidden=True) + res = run_shell_cmd(cmd) return res.output @@ -212,7 +212,7 @@ def get_site_suffix(tag): """ perl_cmd = 'my $a = $Config::Config{"%s"}; $a =~ s/($Config::Config{"siteprefix"})//; print $a' % tag cmd = "perl -MConfig -e '%s'" % perl_cmd - res = run_shell_cmd(cmd, hidden=True) + res = run_shell_cmd(cmd) sitesuffix = res.output # obtained value usually contains leading '/', so strip it off return sitesuffix.lstrip(os.path.sep) From b4ba01e5e0d91d5ffde2b8bdfa3e76d851416c73 Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 11 Dec 2024 11:28:36 +0100 Subject: [PATCH 08/10] Revert "replace make_module_req_guess with module_load_environment in FlexiBLAS easyblock" This reverts commit 0000f5dbe82fbb4ee24c79826e970a34f55ac306. --- easybuild/easyblocks/f/flexiblas.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/easybuild/easyblocks/f/flexiblas.py b/easybuild/easyblocks/f/flexiblas.py index feee155280b..b3d51293855 100644 --- a/easybuild/easyblocks/f/flexiblas.py +++ b/easybuild/easyblocks/f/flexiblas.py @@ -85,9 +85,6 @@ def __init__(self, *args, **kwargs): self.obj_builddir = os.path.join(self.builddir, 'easybuild_obj') - # custom CPATH to FlexiBLAS headers - self.module_load_environment.CPATH = [os.path.join('include', 'flexiblas')] - def configure_step(self): """Custom configuration for FlexiBLAS, based on which BLAS libraries are included as dependencies.""" @@ -226,3 +223,12 @@ def sanity_check_step(self): custom_commands.append("flexiblas list | grep %s" % blas_lib.upper()) super(EB_FlexiBLAS, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) + + def make_module_req_guess(self): + """Customize CPATH for FlexiBLAS.""" + + guesses = super(EB_FlexiBLAS, self).make_module_req_guess() + + guesses.update({'CPATH': [os.path.join('include', 'flexiblas')]}) + + return guesses From 6e80a653ccda36c851aafd693c5ec907842f84bd Mon Sep 17 00:00:00 2001 From: Alex Domingo Date: Wed, 11 Dec 2024 11:28:37 +0100 Subject: [PATCH 09/10] Revert "replace make_module_req_guess with module_load_environment in PythonPackage easyblock" This reverts commit a452f274cd308edb4e0b6c6094224ff4421ccd84. --- easybuild/easyblocks/generic/pythonpackage.py | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/easybuild/easyblocks/generic/pythonpackage.py b/easybuild/easyblocks/generic/pythonpackage.py index 7e02c232e8d..f45cc6c8e16 100644 --- a/easybuild/easyblocks/generic/pythonpackage.py +++ b/easybuild/easyblocks/generic/pythonpackage.py @@ -48,7 +48,7 @@ from easybuild.framework.easyconfig.templates import PYPI_SOURCE from easybuild.framework.extensioneasyblock import ExtensionEasyBlock from easybuild.tools.build_log import EasyBuildError, print_msg -from easybuild.tools.config import build_option, PYTHONPATH, EBPYTHONPREFIXES, SEARCH_PATH_LIB_DIRS +from easybuild.tools.config import build_option, PYTHONPATH, EBPYTHONPREFIXES from easybuild.tools.filetools import change_dir, mkdir, remove_dir, symlink, which from easybuild.tools.modules import get_software_root from easybuild.tools.run import run_shell_cmd, subprocess_popen_text @@ -1148,30 +1148,27 @@ def sanity_check_step(self, *args, **kwargs): return (parent_success and success, parent_fail_msg + fail_msg) - def make_module_step(self, *args, **kwargs): + def make_module_req_guess(self): """ - Define list of subdirectories in search paths of module load environment + Define list of subdirectories to consider for updating path-like environment variables ($PATH, etc.). """ + guesses = super(PythonPackage, self).make_module_req_guess() + # avoid that lib subdirs are appended to $*LIBRARY_PATH if they don't provide libraries # typically, only lib/pythonX.Y/site-packages should be added to $PYTHONPATH (see make_module_extra) - for env_var in ['LD_LIBRARY_PATH', 'LIBRARY_PATH']: - search_paths = getattr(self.module_load_environment, env_var) - for lib_dir in SEARCH_PATH_LIB_DIRS: + for envvar in ['LD_LIBRARY_PATH', 'LIBRARY_PATH']: + newlist = [] + for subdir in guesses[envvar]: # only subdirectories that contain one or more files/libraries should be retained - install_lib_dir = os.path.join(self.installdir, lib_dir) - try: - lib_files = [os.path.isfile(os.path.join(install_lib_dir, x)) for x in os.listdir(install_lib_dir)] - except FileNotFoundError: - lib_files = [] - - if any(lib_files): - search_paths.append(lib_dir) - else: - search_paths.remove(lib_dir) - - self.log.debug(f"Directories retained in module load environment for ${env_var}: [{search_paths}]") - - return super().make_module_step(*args, **kwargs) + fullpath = os.path.join(self.installdir, subdir) + if os.path.exists(fullpath): + if any([os.path.isfile(os.path.join(fullpath, x)) for x in os.listdir(fullpath)]): + newlist.append(subdir) + self.log.debug("Only retaining %s subdirs from %s for $%s (others don't provide any libraries)", + newlist, guesses[envvar], envvar) + guesses[envvar] = newlist + + return guesses def make_module_extra(self, *args, **kwargs): """Add install path to PYTHONPATH""" From 2b906415285e5e7885534cd77b47c84ed54a4d61 Mon Sep 17 00:00:00 2001 From: Kenneth Hoste Date: Mon, 20 Jan 2025 21:39:51 +0100 Subject: [PATCH 10/10] complete migration of Bundle easyblock to module_load_environment + take into account that component easyblocks may still be using make_module_req_guess --- easybuild/easyblocks/generic/bundle.py | 103 ++++++++++++++++--------- 1 file changed, 65 insertions(+), 38 deletions(-) diff --git a/easybuild/easyblocks/generic/bundle.py b/easybuild/easyblocks/generic/bundle.py index 14f5fdfa192..b07d215af93 100644 --- a/easybuild/easyblocks/generic/bundle.py +++ b/easybuild/easyblocks/generic/bundle.py @@ -317,24 +317,42 @@ def install_step(self): else: comp.run_step(step_name, [lambda x: getattr(x, '%s_step' % step_name)]) - # Update current environment with component environment to ensure stuff provided - # by this component can be picked up by installation of subsequent components - # - this is a stripped down version of EasyBlock.make_module_req for fake modules - # - once bundle installation is complete, this is handled by the generated module as usual - for mod_envar, mod_paths in comp.module_load_environment.items(): - # expand glob patterns in module load environment to existing absolute paths - mod_expand = [x for p in mod_paths for x in comp.expand_module_search_path(p, False, fake=True)] - mod_expand = nub(mod_expand) - mod_expand = [os.path.join(self.installdir, path) for path in mod_expand] - # prepend to current environment variable if new stuff added to installation - curr_env = os.getenv(mod_envar, '') - curr_paths = [path for path in curr_env.split(os.pathsep) if path] - new_paths = nub(mod_expand + curr_paths) - new_env = os.pathsep.join(new_paths) - if new_env and new_env != curr_env: - env.setvar(mod_envar, new_env) - - def make_module_req_guess(self): + if comp.make_module_req_guess.__qualname__ != 'EasyBlock.make_module_req_guess': + depr_msg = f"Easyblock used to install component {comp.name} still uses make_module_req_guess" + self.log.deprecated(depr_msg, '6.0') + # update environment to ensure stuff provided by former components can be picked up by latter components + # once the installation is finalised, this is handled by the generated module + reqs = comp.make_module_req_guess() + for envvar in reqs: + curr_val = os.getenv(envvar, '') + curr_paths = curr_val.split(os.pathsep) + for subdir in reqs[envvar]: + path = os.path.join(self.installdir, subdir) + if path not in curr_paths: + if curr_val: + new_val = '%s:%s' % (path, curr_val) + else: + new_val = path + env.setvar(envvar, new_val) + else: + # Update current environment with component environment to ensure stuff provided + # by this component can be picked up by installation of subsequent components + # - this is a stripped down version of EasyBlock.make_module_req for fake modules + # - once bundle installation is complete, this is handled by the generated module as usual + for mod_envar, mod_paths in comp.module_load_environment.items(): + # expand glob patterns in module load environment to existing absolute paths + mod_expand = [x for p in mod_paths for x in comp.expand_module_search_path(p, False)] + mod_expand = nub(mod_expand) + mod_expand = [os.path.join(self.installdir, path) for path in mod_expand] + # prepend to current environment variable if new stuff added to installation + curr_env = os.getenv(mod_envar, '') + curr_paths = [path for path in curr_env.split(os.pathsep) if path] + new_paths = nub(mod_expand + curr_paths) + new_env = os.pathsep.join(new_paths) + if new_env and new_env != curr_env: + env.setvar(mod_envar, new_env) + + def make_module_step(self, *args, **kwargs): """ Set module requirements from all components, e.g. $PATH, etc. During the install step, we only set these requirements temporarily. @@ -346,28 +364,37 @@ def make_module_req_guess(self): 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 + + # take into account that easyblock used for component may not be migrated yet to module_load_environment + if comp.make_module_req_guess.__qualname__ != 'EasyBlock.make_module_req_guess': + + depr_msg = f"Easyblock used to install component {cfg['name']} still uses make_module_req_guess" + self.log.deprecated(depr_msg, '6.0') + + 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 key in self.module_load_environment: + getattr(self.module_load_environment, key).extend(value) + else: + setattr(self.module_load_environment, key, value) + except AttributeError: + raise EasyBuildError("Cannot process module requirements of bundle component %s v%s", + cfg['name'], cfg['version']) + else: + for env_var_name, env_var_val in comp.module_load_environment.items(): + if env_var_name in self.module_load_environment: + getattr(self.module_load_environment, env_var_name).extend(env_var_val) + else: + setattr(self.module_load_environment, env_var_name, env_var_val) + + return super().make_module_step(*args, **kwargs) def make_module_extra(self, *args, **kwargs): """Set extra stuff in module file, e.g. $EBROOT*, $EBVERSION*, etc."""