diff --git a/docs/tutorial_build_automation.rst b/docs/tutorial_build_automation.rst index 85284ffd69..568aa849e6 100644 --- a/docs/tutorial_build_automation.rst +++ b/docs/tutorial_build_automation.rst @@ -109,8 +109,8 @@ Here is the test's code: When :attr:`~reframe.core.pipeline.RegressionTest.build_system` is set to ``'Spack'``, ReFrame will leverage Spack environments in order to build the test code. -For this reason, currently, users must specify an environment. -ReFrame treats Spack environments as *test resources* so it expects to find them under the test's :attr:`~reframe.core.pipeline.RegressionTest.sourcesdir`, which defaults to ``'src'``. +If the environment is not specified by the user, ReFrame will automatically create one inside the stage directory. +ReFrame treats Spack environments specified by the user as *test resources* so it expects to find them under the test's :attr:`~reframe.core.pipeline.RegressionTest.sourcesdir`, which defaults to ``'src'``. Here is the directory structure for the test in this particular example that we show here: .. code:: console diff --git a/reframe/core/buildsystems.py b/reframe/core/buildsystems.py index 07c09f73c2..9f2ce2e357 100644 --- a/reframe/core/buildsystems.py +++ b/reframe/core/buildsystems.py @@ -780,11 +780,41 @@ class Spack(BuildSystem): #: ReFrame looks for environments in the test's #: :attr:`~reframe.core.pipeline.RegressionTest.sourcesdir`. #: - #: This field is required. + #: If this field is `None`, the default, the environment name will + #: be automatically set to `rfm_spack_env`. #: #: :type: :class:`str` or :class:`None` - #: :default: :class:`required` - environment = variable(typ.Str[r'\S+']) + #: :default: :class:`None` + #: + #: .. note:: + #: .. versionchanged:: 3.7.3 + #: The field is no longer required and the Spack environment will be + #: automatically created if not provided. + environment = variable(typ.Str[r'\S+'], type(None), value=None) + + #: The directory where Spack will install the packages requested by this + #: test. + #: + #: After activating the Spack environment, ReFrame will set the + #: `install_tree` Spack configuration in the given environment with the + #: following command: + #: + #: .. code-block:: bash + #: + #: spack config add "config:install_tree:root:" + #: + #: Relative paths are resolved against the test's stage directory. If this + #: field and the Spack environment are both `None`, the default, the + #: install directory will be automatically set to `opt/spack`. If this + #: field `None` but the Spack environment is not, then `install_tree` will + #: not be set automatically and the install tree of the given environment + #: will not be overridden. + #: + #: :type: :class:`str` or :class:`None` + #: :default: :class:`None` + #: + #: .. versionadded:: 3.7.3 + install_tree = variable(typ.Str[r'\S+'], type(None), value=None) #: A list of additional specs to build and install within the given #: environment. @@ -816,10 +846,13 @@ class Spack(BuildSystem): install_opts = variable(typ.List[str], value=[]) def emit_build_commands(self, environ): - if not hasattr(self, 'environment'): - raise BuildSystemError(f'no Spack environment is defined') - ret = self._env_activate_cmds() + + if not self.environment: + install_tree = self.install_tree or 'opt/spack' + ret.append(f'spack config add ' + f'"config:install_tree:root:{install_tree}"') + if self.specs: specs_str = ' '.join(self.specs) ret.append(f'spack add {specs_str}') @@ -832,8 +865,15 @@ def emit_build_commands(self, environ): return ret def _env_activate_cmds(self): - return [f'. $SPACK_ROOT/share/spack/setup-env.sh', - f'spack env activate -V -d {self.environment}'] + cmds = ['. $SPACK_ROOT/share/spack/setup-env.sh'] + if self.environment: + environment = self.environment + else: + environment = 'rfm_spack_env' + cmds.append(f'spack env create -d {environment}') + + cmds.append(f'spack env activate -V -d {environment}') + return cmds def prepare_cmds(self): cmds = self._env_activate_cmds() diff --git a/unittests/test_buildsystems.py b/unittests/test_buildsystems.py index 45c2d975c4..403fba66da 100644 --- a/unittests/test_buildsystems.py +++ b/unittests/test_buildsystems.py @@ -280,9 +280,14 @@ def test_spack_with_spec(environ, tmp_path): def test_spack_no_env(environ, tmp_path): build_system = bs.Spack() - with pytest.raises(BuildSystemError): - build_system.emit_build_commands(environ) - + with osext.change_dir(tmp_path): + assert build_system.emit_build_commands(environ) == [ + f'. $SPACK_ROOT/share/spack/setup-env.sh', + f'spack env create -d rfm_spack_env', + f'spack env activate -V -d rfm_spack_env', + f'spack config add "config:install_tree:root:opt/spack"', + f'spack install' + ] def test_easybuild(environ, tmp_path): build_system = bs.EasyBuild()