From 54313bbcc6d9a3e9045396df8be3279e388821f5 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Fri, 18 Jan 2019 21:34:13 +0100 Subject: [PATCH] Added compiler detection for Cray front-end --- lib/spack/spack/compilers/__init__.py | 18 ++-- .../spack/operating_systems/cray_frontend.py | 89 +++++++++++-------- 2 files changed, 64 insertions(+), 43 deletions(-) diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py index 297a4b5c90a..ed9c2b26d9e 100644 --- a/lib/spack/spack/compilers/__init__.py +++ b/lib/spack/spack/compilers/__init__.py @@ -205,7 +205,7 @@ def find_compilers(*path_hints): # of arguments for each call. arguments = [] for o in all_os_classes(): - arguments.extend(arguments_to_detect_version_fn(o, *paths)) + arguments.extend(arguments_to_detect_version_fn(o, paths)) # Here we map the function arguments to the corresponding calls tp = multiprocessing.pool.ThreadPool() @@ -462,7 +462,7 @@ def all_compiler_types(): ) -def arguments_to_detect_version_fn(operating_system, *paths): +def arguments_to_detect_version_fn(operating_system, paths, override=True): """Returns a list of DetectVersionArgs tuples to be used in a corresponding function to detect compiler versions. @@ -472,14 +472,16 @@ def arguments_to_detect_version_fn(operating_system, *paths): Args: operating_system (OperatingSystem): the operating system on which we are looking for compilers - *paths: paths to search for compilers + paths: paths to search for compilers + override (bool): whether we should search for an override to this + function in the operating system class Returns: List of DetectVersionArgs tuples. Each item in the list will be later mapped to the corresponding function call to detect the version of the compilers in this OS. """ - def _default(*search_paths): + def _default(search_paths): command_arguments = [] files_to_be_tested = fs.files_in(*search_paths) for compiler_name in spack.compilers.supported_compilers(): @@ -509,8 +511,12 @@ def _default(*search_paths): # does not spoil the intended precedence. return reversed(command_arguments) - fn = getattr(operating_system, 'arguments_to_detect_version_fn', _default) - return fn(*paths) + fn = _default + if override: + fn = getattr( + operating_system, 'arguments_to_detect_version_fn', _default + ) + return fn(paths) def detect_version(detect_version_args): diff --git a/lib/spack/spack/operating_systems/cray_frontend.py b/lib/spack/spack/operating_systems/cray_frontend.py index 7b6359c5b8f..5c034b05cf8 100644 --- a/lib/spack/spack/operating_systems/cray_frontend.py +++ b/lib/spack/spack/operating_systems/cray_frontend.py @@ -3,52 +3,67 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import contextlib import os +import llnl.util.filesystem as fs + from spack.operating_systems.linux_distro import LinuxDistro +from spack.util.environment import get_path from spack.util.module_cmd import module +@contextlib.contextmanager +def unload_programming_environment(): + """Context manager that unloads Cray Programming Environments.""" + env_bu = None + + # We rely on the fact that the PrgEnv-* modules set the PE_ENV + # environment variable. + if 'PE_ENV' in os.environ: + # Copy environment variables to restore them after the compiler + # detection. We expect that the only thing PrgEnv-* modules do is + # the environment variables modifications. + env_bu = os.environ.copy() + + # Get the name of the module from the environment variable. + prg_env = 'PrgEnv-' + os.environ['PE_ENV'].lower() + + # Unload the PrgEnv-* module. By doing this we intentionally + # provoke errors when the Cray's compiler wrappers are executed + # (Error: A PrgEnv-* modulefile must be loaded.) so they will not + # be detected as valid compilers by the overridden method. We also + # expect that the modules that add the actual compilers' binaries + # into the PATH environment variable (i.e. the following modules: + # 'intel', 'cce', 'gcc', etc.) will also be unloaded since they are + # specified as prerequisites in the PrgEnv-* modulefiles. + module('unload', prg_env) + + yield + + # Restore the environment. + if env_bu is not None: + os.environ.clear() + os.environ.update(env_bu) + + class CrayFrontend(LinuxDistro): """Represents OS that runs on login and service nodes of the Cray platform. It acts as a regular Linux without Cray-specific modules and compiler wrappers.""" - def find_compilers(self, *paths): - """Calls the overridden method but prevents it from detecting Cray - compiler wrappers to avoid possible false detections. The detected - compilers come into play only if a user decides to work with the Cray's - frontend OS as if it was a regular Linux environment.""" + def arguments_to_detect_version_fn(self, paths): + """Calls the default function but prevents it from detecting Cray + compiler wrappers to avoid possible false detections. - env_bu = None - - # We rely on the fact that the PrgEnv-* modules set the PE_ENV - # environment variable. - if 'PE_ENV' in os.environ: - # Copy environment variables to restore them after the compiler - # detection. We expect that the only thing PrgEnv-* modules do is - # the environment variables modifications. - env_bu = os.environ.copy() - - # Get the name of the module from the environment variable. - prg_env = 'PrgEnv-' + os.environ['PE_ENV'].lower() - - # Unload the PrgEnv-* module. By doing this we intentionally - # provoke errors when the Cray's compiler wrappers are executed - # (Error: A PrgEnv-* modulefile must be loaded.) so they will not - # be detected as valid compilers by the overridden method. We also - # expect that the modules that add the actual compilers' binaries - # into the PATH environment variable (i.e. the following modules: - # 'intel', 'cce', 'gcc', etc.) will also be unloaded since they are - # specified as prerequisites in the PrgEnv-* modulefiles. - module('unload', prg_env) - - # Call the overridden method. - clist = super(CrayFrontend, self).find_compilers(*paths) - - # Restore the environment. - if env_bu is not None: - os.environ.clear() - os.environ.update(env_bu) - - return clist + The detected compilers come into play only if a user decides to + work with the Cray's frontend OS as if it was a regular Linux + environment. + """ + import spack.compilers + with unload_programming_environment(): + search_paths = fs.search_paths_for_executables(*get_path('PATH')) + args = spack.compilers.arguments_to_detect_version_fn( + self, search_paths, override=False + ) + return args