From f815e3387ddbaad2a6fb40ae1536e1b26e8aa4cd Mon Sep 17 00:00:00 2001 From: Douglas Jacobsen Date: Thu, 26 Oct 2023 12:28:05 -0600 Subject: [PATCH] Fix nested compiler install This commit fixes compiler installation. Previously, if a compiler needed to be installed, and was required to be installed with a different specific compiler the installation specs were incorrect. This commit extracts and installs all compilers, including the compilers they are dependent on. --- lib/ramble/ramble/application_types/spack.py | 27 ++++- .../nested_compilers_are_installed.py | 98 +++++++++++++++++++ 2 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 lib/ramble/ramble/test/end_to_end/nested_compilers_are_installed.py diff --git a/lib/ramble/ramble/application_types/spack.py b/lib/ramble/ramble/application_types/spack.py index e4aff1634..770fd897b 100644 --- a/lib/ramble/ramble/application_types/spack.py +++ b/lib/ramble/ramble/application_types/spack.py @@ -82,11 +82,11 @@ def _long_print(self): def _software_install_requested_compilers(self, workspace): """Install compilers an application uses""" - # See if we cached this already, and if so return env_path = self.expander.env_path if not env_path: raise ApplicationError('Ramble env_path is set to None.') + logger.msg('Installing compilers') cache_tupl = ('spack-compilers', env_path) if workspace.check_cache(cache_tupl): @@ -101,13 +101,30 @@ def _software_install_requested_compilers(self, workspace): app_context = self.expander.expand_var_name(self.keywords.env_name) + compilers_to_install = set() + root_compilers = [] for pkg_name in workspace.software_environments.get_env_packages(app_context): pkg_spec = workspace.software_environments.get_spec(pkg_name) if 'compiler' in pkg_spec: - logger.msg('Installing compilers') - logger.debug(f'Compilers: {pkg_spec["compiler"]}') - comp_spec = workspace.software_environments.get_spec(pkg_spec['compiler']) - self.spack_runner.install_compiler(comp_spec['spack_spec']) + if pkg_spec['compiler'] not in compilers_to_install: + logger.debug(f' Adding root compiler: {pkg_spec["compiler"]}') + compilers_to_install.add(pkg_spec['compiler']) + root_compilers.append(pkg_spec['compiler']) + + dep_compilers = [] + for comp_name in root_compilers: + cur_spec = workspace.software_environments.get_spec(comp_name) + while 'compiler' in cur_spec and cur_spec['compiler'] not in compilers_to_install: + compilers_to_install.add(cur_spec['compiler']) + dep_compilers.append(cur_spec['compiler']) + logger.debug(f' Adding dependency compiler: {cur_spec["compiler"]}') + cur_spec = workspace.software_environments.get_spec(cur_spec['compiler']) + + # Install all compilers, starting with deps: + for comp_pkg in reversed(root_compilers + dep_compilers): + spec_str = workspace.software_environments.get_spec_string(comp_pkg) + logger.debug(f'Installing compiler: {comp_pkg}') + self.spack_runner.install_compiler(spec_str) except ramble.spack_runner.RunnerError as e: logger.die(e) diff --git a/lib/ramble/ramble/test/end_to_end/nested_compilers_are_installed.py b/lib/ramble/ramble/test/end_to_end/nested_compilers_are_installed.py new file mode 100644 index 000000000..0907fd747 --- /dev/null +++ b/lib/ramble/ramble/test/end_to_end/nested_compilers_are_installed.py @@ -0,0 +1,98 @@ +# Copyright 2022-2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import os +import glob + +import pytest + +import ramble.filters +import ramble.pipeline +import ramble.workspace +import ramble.config +import ramble.software_environments +from ramble.main import RambleCommand +from ramble.test.dry_run_helpers import search_files_for_string + + +# everything here uses the mock_workspace_path +pytestmark = pytest.mark.usefixtures('mutable_config', + 'mutable_mock_workspace_path') + +workspace = RambleCommand('workspace') + + +def test_nested_compilers_are_installed(mutable_config, mutable_mock_workspace_path, capsys): + test_config = """ +ramble: + variables: + mpi_command: 'mpirun -n {n_ranks} -ppn {processes_per_node}' + batch_submit: 'batch_submit {execute_experiment}' + processes_per_node: '10' + n_ranks: '{processes_per_node}*{n_nodes}' + n_threads: '1' + applications: + wrfv4: + workloads: + CONUS_12km: + experiments: + test{n_nodes}_{env_name}: + variables: + n_nodes: '1' + spack: + concretized: true + packages: + gcc8: + spack_spec: gcc@8.5.0 + gcc9: + spack_spec: gcc@9.3.0 + compiler: gcc8 + gcc10: + spack_spec: gcc@10.1.0 + compiler: gcc9 + intel: + spack_spec: intel-mpi@2018.4.274 + compiler: gcc10 + wrf: + spack_spec: wrf@4.2 build_type=dm+sm compile_type=em_real nesting=basic ~chem ~pnetcdf + compiler: gcc10 + environments: + wrfv4: + packages: + - wrf + - intel +""" + + setup_type = ramble.pipeline.pipelines.setup + setup_cls = ramble.pipeline.pipeline_class(setup_type) + filters = ramble.filters.Filters() + + workspace_name = 'test_nested_compilers_are_installed' + with ramble.workspace.create(workspace_name) as ws: + ws.write() + + config_path = os.path.join(ws.config_dir, ramble.workspace.config_file_name) + + with open(config_path, 'w+') as f: + f.write(test_config) + + ws.dry_run = True + ws._re_read() + + setup_pipeline = setup_cls(ws, filters) + setup_pipeline.run() + + gcc8_str = "gcc@8.5.0" + gcc9_str = "gcc@9.3.0" + gcc10_str = "gcc@10.1.0" + + out_files = glob.glob(os.path.join(ws.log_dir, '**', '*.out'), recursive=True) + + assert search_files_for_string(out_files, gcc8_str) is True + assert search_files_for_string(out_files, gcc9_str) is True + assert search_files_for_string(out_files, gcc10_str) is True