diff --git a/docs/tutorial_build_automation.rst b/docs/tutorial_build_automation.rst index a656cfc136..a2d9db5ca9 100644 --- a/docs/tutorial_build_automation.rst +++ b/docs/tutorial_build_automation.rst @@ -108,6 +108,8 @@ By default, ReFrame will create a new Spack environment in the test's stage dire .. note:: Optional spec attributes, such as ``target`` and ``os``, should be specified in :attr:`~reframe.core.buildsystems.Spack.specs` and not as install options in :attr:`~reframe.core.buildsystems.Spack.install_opts`. +You can set Spack configuration options for the new environment with the :attr:`~reframe.core.buildsystems.Spack.config_opts` attribute. These options take precedence over Spack's ``spack.yaml`` defaults. + Users may also specify an existing Spack environment by setting the :attr:`~reframe.core.buildsystems.Spack.environment` attribute. In this case, ReFrame treats the environment as a *test resource* so it expects to find it under the test's :attr:`~reframe.core.pipeline.RegressionTest.sourcesdir`, which defaults to ``'src'``. diff --git a/reframe/core/buildsystems.py b/reframe/core/buildsystems.py index 2ee6a8c64b..b1ec437896 100644 --- a/reframe/core/buildsystems.py +++ b/reframe/core/buildsystems.py @@ -869,6 +869,14 @@ class Spack(BuildSystem): #: :default: ``[]`` install_opts = variable(typ.List[str], value=[]) + #: A list of Spack configurations in flattened YAML. + #: + #: :type: :class:`List[str]` + #: :default: ``[]`` + #: + #: .. versionadded:: 4.2 + config_opts = variable(typ.List[str], value=[]) + def __init__(self): # Set to True if the environment was auto-generated self._auto_env = False @@ -876,10 +884,14 @@ def __init__(self): def emit_build_commands(self, environ): ret = self._create_env_cmds() + config_opts = [] if self._auto_env: install_tree = self.install_tree or 'opt/spack' - ret.append(f'spack -e {self.environment} config add ' - f'"config:install_tree:root:{install_tree}"') + config_opts.append(f'config:install_tree:root:{install_tree}') + + config_opts += self.config_opts + for opt in config_opts: + ret.append(f'spack -e {self.environment} config add "{opt}"') if self.specs: specs_str = ' '.join(self.specs) diff --git a/unittests/test_buildsystems.py b/unittests/test_buildsystems.py index 8350acbff9..e34092f30f 100644 --- a/unittests/test_buildsystems.py +++ b/unittests/test_buildsystems.py @@ -302,6 +302,20 @@ def test_spack_no_env(environ, tmp_path): assert build_system.environment == 'rfm_spack_env' +def test_spack_env_config(environ, tmp_path): + build_system = bs.Spack() + build_system.config_opts = ['section1:header1:value1', + 'section2:header2:value2'] + with osext.change_dir(tmp_path): + assert build_system.emit_build_commands(environ) == [ + 'spack env create -d rfm_spack_env', + 'spack -e rfm_spack_env config add "config:install_tree:root:opt/spack"', # noqa: E501 + 'spack -e rfm_spack_env config add "section1:header1:value1"', + 'spack -e rfm_spack_env config add "section2:header2:value2"', + 'spack -e rfm_spack_env install', + ] + + def test_easybuild(environ, tmp_path): build_system = bs.EasyBuild() build_system.easyconfigs = ['ec1.eb', 'ec2.eb']