diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 4d9b4fbdd7..73f418f7f0 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -2378,11 +2378,11 @@ def handle_iterate_opts(self): # handle configure/build/install options that are specified as lists (+ perhaps builddependencies) # set first element to be used, keep track of list in self.iter_opts # only needs to be done during first iteration, since after that the options won't be lists anymore - if self.iter_idx == 0: + if self.iter_idx == 0 and self.cfg.iterate_options: # keep track of list, supply first element as first option to handle - for opt in self.cfg.iterate_options: + for opt in ITERATE_OPTIONS: self.iter_opts[opt] = self.cfg[opt] # copy - self.log.debug("Found list for %s: %s", opt, self.iter_opts[opt]) + self.log.debug("Iterating opt %s: %s", opt, self.iter_opts[opt]) if self.iter_opts: print_msg("starting iteration #%s ..." % self.iter_idx, log=self.log, silent=self.silent) @@ -2390,7 +2390,12 @@ def handle_iterate_opts(self): # pop first element from all iterative easyconfig parameters as next value to use for opt, value in self.iter_opts.items(): - if len(value) > self.iter_idx: + if opt not in self.cfg.iterate_options: + # Use original value even for options that were specified as strings so don't change + # (ie. elements in ITERATE_OPTIONS but not in self.cfg.iterate_options), so they + # are restored after an easyblock such as CMakeMake changes them + self.cfg[opt] = value + elif len(value) > self.iter_idx: self.cfg[opt] = value[self.iter_idx] else: self.cfg[opt] = '' # empty list => empty option as next value diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index de3b3e5198..b184473d7b 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -44,7 +44,7 @@ from easybuild.base import fancylogger from easybuild.framework.easyblock import EasyBlock, get_easyblock_instance from easybuild.framework.easyconfig import CUSTOM -from easybuild.framework.easyconfig.easyconfig import EasyConfig +from easybuild.framework.easyconfig.easyconfig import EasyConfig, ITERATE_OPTIONS from easybuild.framework.easyconfig.tools import avail_easyblocks, process_easyconfig from easybuild.framework.extensioneasyblock import ExtensionEasyBlock from easybuild.tools import LooseVersion, config @@ -1173,7 +1173,9 @@ def test_handle_iterate_opts(self): self.assertEqual(eb.cfg.iterate_options, []) self.assertEqual(eb.cfg['configopts'], ["--opt1 --anotheropt", "--opt2", "--opt3 --optbis"]) - expected_iter_opts = {'configopts': ["--opt1 --anotheropt", "--opt2", "--opt3 --optbis"]} + expected_iter_opts = dict.fromkeys(ITERATE_OPTIONS, "") + expected_iter_opts['builddependencies'] = [] + expected_iter_opts['configopts'] = ["--opt1 --anotheropt", "--opt2", "--opt3 --optbis"] # once iteration mode is set, we're still in iteration #0 self.mock_stdout(True) @@ -1185,6 +1187,8 @@ def test_handle_iterate_opts(self): self.assertEqual(eb.cfg.iterating, True) self.assertEqual(eb.cfg.iterate_options, ['configopts']) self.assertEqual(eb.cfg['configopts'], "--opt1 --anotheropt") + # mimic easyblock that changes this in-place + eb.cfg['preconfigopts'] = "FOO=bar " self.assertEqual(eb.iter_opts, expected_iter_opts) # when next iteration is start, iteration index gets bumped @@ -1196,6 +1200,8 @@ def test_handle_iterate_opts(self): self.assertEqual(stdout, "== starting iteration #1 ...\n") self.assertEqual(eb.cfg.iterating, True) self.assertEqual(eb.cfg.iterate_options, ['configopts']) + # preconfigopts should have been restored (https://github.com/easybuilders/easybuild-framework/pull/4848) + self.assertEqual(eb.cfg['preconfigopts'], "") self.assertEqual(eb.cfg['configopts'], "--opt2") self.assertEqual(eb.iter_opts, expected_iter_opts)