diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 2a9a411c65..16f1770b7e 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -1463,21 +1463,30 @@ def make_module_extra_extensions(self): Sets optional variables for extensions. """ # add stuff specific to individual extensions - lines = [self.module_extra_extensions] + txt = self.module_extra_extensions + + if not self.ext_instances: + self.prepare_for_extensions() + self.init_ext_instances() + + for ext in self.ext_instances: + ext_txt = ext.make_extension_module_extra() + if ext_txt: + txt += ext_txt # set environment variable that specifies list of extensions # We need only name and version, so don't resolve templates exts_list = self.make_extension_string(ext_sep=',', sort=False) env_var_name = convert_name(self.name, upper=True) - lines.append(self.module_generator.set_environment('EBEXTSLIST%s' % env_var_name, exts_list)) + txt += self.module_generator.set_environment('EBEXTSLIST%s' % env_var_name, exts_list) - return ''.join(lines) + return txt def make_module_footer(self): """ Insert a footer section in the module file, primarily meant for contextual information """ - footer = [self.module_generator.comment("Built with EasyBuild version %s" % VERBOSE_VERSION).rstrip('\n')] + footer = [] # add extra stuff for extensions (if any) if self.cfg.get_ref('exts_list'): @@ -1504,6 +1513,7 @@ def make_module_footer(self): self.log.warning("Not including footer in Lua syntax in non-Lua module file: %s", self.cfg['modluafooter']) + footer.append(self.module_generator.comment("Built with EasyBuild version %s" % VERBOSE_VERSION)) return '\n'.join(footer) def make_module_extend_modpath(self): diff --git a/easybuild/framework/extension.py b/easybuild/framework/extension.py index 56f242ffce..8c2f3f951d 100644 --- a/easybuild/framework/extension.py +++ b/easybuild/framework/extension.py @@ -247,6 +247,10 @@ def toolchain(self): """ return self.master.toolchain + def make_extension_module_extra(self): + """Similar to make_module_extra but only called for extensions""" + return '' + def sanity_check_step(self): """ Sanity check to run after installing extension diff --git a/easybuild/framework/extensioneasyblock.py b/easybuild/framework/extensioneasyblock.py index efd7c349f7..d33526b373 100644 --- a/easybuild/framework/extensioneasyblock.py +++ b/easybuild/framework/extensioneasyblock.py @@ -217,6 +217,6 @@ def make_module_extra(self, extra=None): """Add custom entries to module.""" txt = EasyBlock.make_module_extra(self) - if extra is not None: + if extra: txt += extra return txt diff --git a/test/framework/easyconfig.py b/test/framework/easyconfig.py index c43c84be0e..209385993d 100644 --- a/test/framework/easyconfig.py +++ b/test/framework/easyconfig.py @@ -475,6 +475,7 @@ def test_exts_list(self): homepage = "http://example.com" description = "test easyconfig" toolchain = SYSTEM + exts_defaultclass = "DummyExtension" exts_default_options = { "source_tmpl": "gzip-1.4.eb", # dummy source template to avoid download fail "source_urls": ["http://example.com/%(name)s/%(version)s"] diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py b/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py index 9335611f58..94e9065544 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py @@ -99,6 +99,15 @@ def postrun(self): EB_toy.install_step(self.master, name=self.name) + def make_extension_module_extra(self): + """Extra stuff for toy extensions""" + txt = super(Toy_Extension, self).make_extension_module_extra() + value = self.name + if self.version: + value += '-' + self.version + txt += self.module_generator.set_environment('TOY_EXT_VAR', value) + return txt + def sanity_check_step(self, *args, **kwargs): """Custom sanity check for toy extensions.""" self.log.info("Loaded modules: %s", self.modules_tool.list()) diff --git a/test/framework/toy_build.py b/test/framework/toy_build.py index 9416bee2be..2aa4d9bcaf 100644 --- a/test/framework/toy_build.py +++ b/test/framework/toy_build.py @@ -1105,6 +1105,8 @@ def test_toy_advanced(self): # set by ToyExtension easyblock used to install extensions '^setenv.*TOY_EXT_BAR.*bar', '^setenv.*TOY_EXT_BARBAR.*barbar', + '^setenv.*TOY_EXT_VAR.*bar', + '^setenv.*TOY_EXT_VAR.*barbar', ] for pattern in patterns: self.assertTrue(re.search(pattern, toy_mod_txt, re.M), "Pattern '%s' found in: %s" % (pattern, toy_mod_txt)) @@ -1530,8 +1532,8 @@ def test_toy_module_fulltxt(self): ] + modloadmsg_lua + [ r'end', r'setenv\("TOY", "toy-0.0"\)', - r'-- Built with EasyBuild version .*', r'io.stderr:write\("oh hai\!"\)', + r'-- Built with EasyBuild version .*', ]) elif get_module_syntax() == 'Tcl': mod_txt_regex_pattern = '\n'.join([ @@ -1571,8 +1573,8 @@ def test_toy_module_fulltxt(self): ] + modloadmsg_tcl + [ r'}', r'setenv TOY "toy-0.0"', - r'# Built with EasyBuild version .*', r'puts stderr "oh hai\!"', + r'# Built with EasyBuild version .*', ]) else: self.fail("Unknown module syntax: %s" % get_module_syntax()) @@ -1802,6 +1804,8 @@ def test_module_only_extensions(self): # first try normal --module-only, should work fine self.eb_main([test_ec, '--module-only'], do_build=True, raise_error=True) self.assertExists(toy_mod) + # Extra stuff from extension(s) is included + self.assertRegex(read_file(toy_mod), 'TOY_EXT_VAR.*barbar-0.0') remove_file(toy_mod) # rename file required for barbar extension, so we can check whether sanity check catches it @@ -1856,6 +1860,13 @@ def test_toy_exts_parallel(self): stdout, stderr = self.run_test_toy_build_with_output(ec_file=test_ec, extra_args=args) self.assertEqual(stderr, '') + # Extra stuff from extension(s) should be included + ext_var_patterns = [ + 'TOY_EXT_VAR.*ls', + 'TOY_EXT_VAR.*bar-0.0', + 'TOY_EXT_VAR.*barbar-0.0', + ] + # take into account that each of these lines may appear multiple times, # in case no progress was made between checks patterns = [ @@ -1870,6 +1881,10 @@ def test_toy_exts_parallel(self): error_msg = "Expected pattern '%s' should be found in %s'" % (regex.pattern, stdout) self.assertRegex(stdout, regex) + module_contents = read_file(toy_mod) + for pattern in ext_var_patterns: + self.assertRegex(module_contents, pattern) + # also test skipping of extensions in parallel args.append('--skip') stdout, stderr = self.run_test_toy_build_with_output(ec_file=test_ec, extra_args=args) @@ -1888,6 +1903,10 @@ def test_toy_exts_parallel(self): error_msg = "Expected pattern '%s' should be found in %s'" % (regex.pattern, stdout) self.assertTrue(regex.search(stdout), error_msg) + module_contents = read_file(toy_mod) + for pattern in ext_var_patterns: + self.assertRegex(module_contents, pattern) + # check behaviour when using Toy_Extension easyblock that doesn't implement required_deps method; # framework should fall back to installing extensions sequentially toy_ext_eb = os.path.join(topdir, 'sandbox', 'easybuild', 'easyblocks', 'generic', 'toy_extension.py') @@ -1915,6 +1934,10 @@ def test_toy_exts_parallel(self): error_msg = "Expected pattern '%s' should be found in %s'" % (regex.pattern, stdout) self.assertTrue(regex.search(stdout), error_msg) + module_contents = read_file(toy_mod) + for pattern in ext_var_patterns: + self.assertRegex(module_contents, pattern) + def test_backup_modules(self): """Test use of backing up of modules with --module-only."""