From 23b8d916d97872fa77e8c3ae1d93aac3ca3f9e9c Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Thu, 13 Aug 2026 15:40:17 +1000 Subject: [PATCH 1/9] #102 Added first version of Fab build script. --- fab/fab_jules.py | 314 ++++++++++++++++++ fab/site_specific/default/config.py | 153 +++++++++ .../default/setup_script_cray.py | 117 +++++++ fab/site_specific/default/setup_script_gnu.py | 92 +++++ .../default/setup_script_intel_classic.py | 105 ++++++ .../default/setup_script_intel_llvm.py | 87 +++++ .../default/setup_script_nvidia.py | 105 ++++++ 7 files changed, 973 insertions(+) create mode 100755 fab/fab_jules.py create mode 100644 fab/site_specific/default/config.py create mode 100644 fab/site_specific/default/setup_script_cray.py create mode 100644 fab/site_specific/default/setup_script_gnu.py create mode 100644 fab/site_specific/default/setup_script_intel_classic.py create mode 100644 fab/site_specific/default/setup_script_intel_llvm.py create mode 100644 fab/site_specific/default/setup_script_nvidia.py diff --git a/fab/fab_jules.py b/fab/fab_jules.py new file mode 100755 index 00000000..ff4bf06c --- /dev/null +++ b/fab/fab_jules.py @@ -0,0 +1,314 @@ +#!/usr/bin/env python3 +############################################################################## +# (c) Crown copyright Met Office. All rights reserved. +# For further details please refer to the file COPYRIGHT +# which you should have received as part of this distribution +############################################################################## + +''' +This module contains a BAF-based build script for Jules. +''' + +import argparse +import logging +from pathlib import Path +import sys +from typing import cast, Iterable, Optional, Union + + +from fab.api import (FabBase, fcm_export, Exclude, find_source_files, + git_checkout, Include, root_inc_files) + + +class JulesBuild(FabBase): + ''' + A class to build Jules using BAF as base class. + + :param str name: name of the build. + ''' + + def __init__(self, name: str): + ''' + Build Jules using Fab. + + :name: The base name to use for the project directory + ''' + # If the sources need to be checked out or not + self._checkout = False + + # The revision number to check out (if requested) + self._revision = None + + # The root of the jules repository. Defined in + # handle_command_line_options + self._root = None + + super().__init__(name) + + def define_command_line_options( + self, + parser: Optional[argparse.ArgumentParser] = None + ) -> argparse.ArgumentParser: + ''' + This adds a revision option to the command line options inherited + from the base class. + + :param Optional[argparse.ArgumentParser] parser: a pre-defined + argument parser. If not, a new instance will be created. + :returns: the argument parser with the jules specific options added. + :rtype :py:class:`argparse.ArgumentParser` + ''' + + parser = super().define_command_line_options(parser) + parser = cast(argparse.ArgumentParser, parser) + parser.add_argument( + "--revision", "-r", type=str, default="vn7.8", + help="Sets the Jules revision to checkout (only used if" + "--checkout is used). Defaults to 'vn7.8'.") + parser.add_argument( + "--checkout", default=False, action="store_true", + help="If specified, will checkout jules from git or svn, " + "otherwise this script is excepted to be in a cloned " + "git version.") + parser.add_argument( + "--rivers", default=False, action="store_true", + help="If specified, the stand-alone rivers binary will be " + "compiled.") + parser.add_argument( + "--ascii-out", default=False, action="store_true", + help="If specified, NetCDF will be disabled and output " + "will be in ASCII instead.") + return parser + + def handle_command_line_options(self, + parser: argparse.ArgumentParser) -> None: + ''' + Grab the requested (or default) arguments for checkout and Jules + revision to use and store it in an attribute. Do consistency checks + to make sure a revision is only specified if also a checkout is + requested. + + :param parser: the argument parser. + + :raises ValueError: if a revision is specified, but no checkout + is requested. + ''' + + super().handle_command_line_options(parser) + self._checkout = self.args.checkout + self._revision = self.args.revision + self._ascii_out = self.args.ascii_out + self._rivers = self.args.rivers + if self._rivers: + self.set_root_symbol("river") + + if not self._checkout and "--revision" in sys.argv[1:]: + raise ValueError(f"You specified revision '{self._revision}', " + f"but did not request a checkout.") + + def define_project_name(self, name: str) -> str: + ''' + This method adds version number, ascii output (if selected), and + MPI and OpenMP information to the project name, so these different + binaries can be distinguished. + + :returns: the project directory name to use. + ''' + if self._rivers: + name = name + "-rivers" + if self._revision: + name = name + f"-{self._revision}" + if self.args.ascii_out: + name = name + "-ascii" + if self.args.mpi: + name = name + "-mpi" + if self.args.openmp: + name = name + "-openmp" + return super().define_project_name(name) + + def grab_files_step(self) -> None: + ''' + Extracts all the required Jules source files from the repositories. + + :raises RuntimeError: if no checkout is required, but expected Jules + directory (rose-meta/jules-shared) does not exist, indicating + an invalid directory structure. + ''' + # If no checkout was requested, make sure we have the expected + # repository structure. + if not self._checkout: + # Get the root directory of this Jules: + self._root = Path(__file__).resolve().parents[1] + jules_shared = self._root / "rose-meta" / "jules-shared" + if not jules_shared.exists(): + raise RuntimeError(f"The expected directory '{jules_shared}' " + f"does not exist.") + return + + # Try to grab sources from GitHub, fallback to FCM if that fails + + try: + git_checkout( + self.config, + src="git@github.com:MetOffice/jules", + revision=self._revision, + dst_label="jules.git", + ) + self._root = (self.config.project_workspace + / "source" / "jules.git") + except Exception as e: + logging.warning(f"git_checkout failed: {e}, " + f"falling back to fcm_export") + # We export the whole svn repository, to be consistent with + # using either a local checkout or git checkout + fcm_export( + self.config, + src="fcm:jules.xm_tr", + revision=self._revision, + dst_label="jules.svn", + ) + self._root = self.config.project_workspace / "source" / "jules.svn" + + def find_source_files_step( + self, + path_filters: Optional[Iterable[Union[Exclude, Include]]] = None): + ''' + Finds all the Jules sources files to analyse. + + :param path_filters: optional list of path filters to be passed to + Fab find_source_files, default is None. + ''' + if path_filters: + local_filters = path_filters.copy() + else: + local_filters = [] + local_filters.extend([ + Exclude("src/control/um/"), + Exclude("src/initialisation/um/"), + Exclude("src/params/shared/cable_maths_constants_mod.F90"), + ] + ) + if self._rivers: + # The order is important, the last include/exclude statement + # takes precedence. So exclude standalone must come before + # including init_initial_mod + local_filters.extend([ + Exclude("src/control/standalone/jules.F90"), + Exclude("src/initialisation/standalone/"), + Include("src/initialisation/standalone/init_initial_mod.F90"), + Include("src/initialisation/standalone/initial_conditions/" + "jules_initial_mod.F90"), + Include("src/initialisation/standalone/init_output_mod.F90"), + Include("src/initialisation/standalone/init_rivers.F90"), + Include("src/initialisation/standalone/init_time_mod.F90"), + Include("src/initialisation/standalone/init_drive_mod.F90"), + Include("src/initialisation/standalone/" + "init_model_environment_mod.F90"), + Include("src/initialisation/standalone/grid/" + "fill_model_grid_arrays_mod.F90"), + Include("src/initialisation/standalone/grid/" + "init_input_grid_mod.F90"), + Include("src/initialisation/standalone/grid/" + "init_river_out_grid_mod.F90"), + Include("src/initialisation/standalone/grid/" + "init_latlon_mod.F90"), + Include("src/initialisation/standalone/grid/" + "init_land_frac_mod.F90"), + Include("src/initialisation/standalone/grid/" + "init_model_grid_mod.F90"), + Include("src/initialisation/standalone/rivers-standalone/" + "ancillaries"), + Include("src/initialisation/standalone/ancillaries/" + "init_rivers_props_mod.F90"), + Include("src/initialisation/standalone/ancillaries/" + "ancil_namelist_mod.F90"), + Include("src/initialisation/standalone/ancillaries/" + "init_ancillaries_coupling_mod.F90"), + Include("src/initialisation/standalone/ancillaries/" + "init_rivers_process_data_mod.F90"), + Include("src/initialisation/standalone/ancillaries/" + "jules_overbank_props_mod.F90"), + Include("src/initialisation/standalone/ancillaries/" + "jules_rivers_props_mod.F90"), + Exclude("src/initialisation/shared/" + "check_compatible_options_mod.F90"), + Exclude("src/control/lfric/check_unavailable_options_mod.F90"), + Exclude("src/io/dump/read_dump_mod.F90"), + Exclude("src/io/dump/write_dump_mod.F90"), + ]) + else: + local_filters.extend([ + Exclude("src/control/rivers-standalone/"), + Exclude("src/io/rivers-standalone"), + Exclude("src/initialisation/rivers-standalone/"), + Exclude("src/control/lfric/check_unavailable_options_mod.F90"), + ]) + + find_source_files(self.config, + source_root=self._root / "src", + path_filters=local_filters) + + # Add the utility files as required + # --------------------------------- + utils = self._root / "utils" + # For now assume dr hook is always disabled, so use dummy + find_source_files(self.config, + source_root=utils / "drhook_dummy") + if not self.config.mpi: + find_source_files(self.config, + source_root=utils / "mpi_dummy") + if self._ascii_out: + find_source_files(self.config, + source_root=utils / "netcdf_dummy") + + # move inc files to the root for easy tool use + root_inc_files(self.config) + + def define_preprocessor_flags_step(self) -> None: + ''' + Defines the preprocessor flags. + ''' + super().define_preprocessor_flags_step() + flags = ["-I$output"] + if not self.config.mpi: + flags.append("-DMPI_DUMMY") + if self._ascii_out: + flags.append("-DNCDF_DUMMY") + + self.add_preprocessor_flags(flags) + + def get_linker_flags(self) -> list[str]: + ''' + Base class for setting linker flags. + :returns: list of flags for the linker. + ''' + libs = [] + if not self._ascii_out: + libs.extend(["netcdf", "hdf5"]) + return libs + + +if __name__ == "__main__": + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + + class NoFabFilter(logging.Filter): + '''A dummy class that disables all Fab noise. + ''' + def filter(self, record): + return not record.name.startswith("fab") + + root_logger = logging.getLogger() + root_logger.setLevel(logging.DEBUG) + last_resort_handler = logging.lastResort + last_resort_handler.setLevel(logging.DEBUG) + + baf_logger = logging.getLogger("baf") + baf_logger.setLevel(logging.DEBUG) + fab_logger = logging.getLogger("fab") + fab_logger.setLevel(logging.WARNING) + fab_handlers = fab_logger.handlers + # fab_handlers[0].addFilter(NoFabFilter()) + + jb = JulesBuild("jules") + jb.build() diff --git a/fab/site_specific/default/config.py b/fab/site_specific/default/config.py new file mode 100644 index 00000000..b15f1a11 --- /dev/null +++ b/fab/site_specific/default/config.py @@ -0,0 +1,153 @@ +#! /usr/bin/env python3 + + +''' +This module contains the default Baf configuration class. +''' + +import argparse +from typing import List + +from fab.api import BuildConfig, Category, ToolRepository + +from default.setup_script_cray import setup_script_cray +from default.setup_script_gnu import setup_script_gnu +from default.setup_script_intel_classic import setup_script_intel_classic +from default.setup_script_intel_llvm import setup_script_intel_llvm +from default.setup_script_nvidia import setup_script_nvidia + + +class Config: + ''' + This class is the default Configuration object for Baf builds. + It provides several callbacks which will be called from the build + scripts to allow site-specific customisations. + ''' + + def __init__(self): + self._args = None + + @property + def args(self) -> argparse.Namespace: + ''' + :returns argparse.Namespace: the command line options specified by + the user. + ''' + return self._args + + def get_valid_profiles(self) -> List[str]: + ''' + Determines the list of all allowed compiler profiles. The first + entry in this list is the default profile to be used. This method + can be overwritten by site configs to add or modify the supported + profiles. + + :returns List[str]: list of all supported compiler profiles. + ''' + return ["full-debug", "fast-debug", "production", "unit-tests"] + + def update_toolbox(self, build_config: BuildConfig) -> None: + ''' + Set the default compiler flags for the various compiler + that are supported. + + :param build_config: the Fab build configuration instance + :type build_config: :py:class:`fab.BuildConfig` + ''' + # First create the default compiler profiles for all available + # compilers. While we have a tool box with exactly one compiler + # in it, compiler wrappers will require more than one compiler + # to be initialised - so we just initialise all of them (including + # the linker): + tr = ToolRepository() + for compiler in (tr[Category.C_COMPILER] + + tr[Category.FORTRAN_COMPILER] + + tr[Category.LINKER]): + if compiler.is_available: + # Define a base profile, which contains the common + # compilation flags. This 'base' is not accessible to + # the user, so it's not part of the profile list. Also, + # make it inherit from the default profile '', so that + # a user does not have to specify the base profile + compiler.define_profile("base", inherit_from="") + for profile in self.get_valid_profiles(): + compiler.define_profile(profile, inherit_from="base") + + self.setup_intel_classic(build_config) + self.setup_intel_llvm(build_config) + self.setup_gnu(build_config) + self.setup_nvidia(build_config) + self.setup_cray(build_config) + + def handle_command_line_options(self, args: argparse.Namespace) -> None: + ''' + Additional callback function executed once all command line + options have been added. This is for example used to add + Vernier profiling flags, which are site-specific. + + :param argparse.Namespace args: the command line options added in + the site configs + ''' + # Keep a copy of the args, so they can be used when + # initialising compilers + self._args = args + + def setup_cray(self, build_config: BuildConfig) -> None: + ''' + This method sets up the Cray compiler and linker flags. + For now call an external function, since it is expected that + this configuration can be very lengthy (once we support + compiler modes). + + :param build_config: the Fab build configuration instance + :type build_config: :py:class:`fab.BuildConfig` + ''' + setup_script_cray(build_config, self.args) + + def setup_gnu(self, build_config: BuildConfig) -> None: + ''' + This method sets up the Gnu compiler and linker flags. + For now call an external function, since it is expected that + this configuration can be very lengthy (once we support + compiler modes). + + :param build_config: the Fab build configuration instance + :type build_config: :py:class:`fab.BuildConfig` + ''' + setup_script_gnu(build_config, self.args) + + def setup_intel_classic(self, build_config: BuildConfig) -> None: + ''' + This method sets up the Intel classic compiler and linker flags. + For now call an external function, since it is expected that + this configuration can be very lengthy (once we support + compiler modes). + + :param build_config: the Fab build configuration instance + :type build_config: :py:class:`fab.BuildConfig` + ''' + setup_script_intel_classic(build_config, self.args) + + def setup_intel_llvm(self, build_config: BuildConfig) -> None: + ''' + This method sets up the Intel LLVM compiler and linker flags. + For now call an external function, since it is expected that + this configuration can be very lengthy (once we support + compiler modes). + + :param build_config: the Fab build configuration instance + :type build_config: :py:class:`fab.BuildConfig` + ''' + setup_script_intel_llvm(build_config, self.args) + + def setup_nvidia(self, build_config: BuildConfig) -> None: + ''' + This method sets up the Nvidia compiler and linker flags. + For now call an external function, since it is expected that + this configuration can be very lengthy (once we support + compiler modes). + + :param build_config: the Fab build configuration instance + :type build_config: :py:class:`fab.BuildConfig` + ''' + setup_script_nvidia(build_config, self.args) diff --git a/fab/site_specific/default/setup_script_cray.py b/fab/site_specific/default/setup_script_cray.py new file mode 100644 index 00000000..f87a6509 --- /dev/null +++ b/fab/site_specific/default/setup_script_cray.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 + +''' +This file contains a function that sets the default flags for the Cray +compilers and linkers in the ToolRepository. + +This function gets called from the default site-specific config file +''' + +import argparse +from typing import cast + +from fab.api import BuildConfig, Category, Compiler, Linker, ToolRepository + + +def setup_script_cray(build_config: BuildConfig, args: argparse.Namespace): + # pylint: disable=unused-argument + ''' + Defines the default flags for ftn. + + :param build_config: the Fab build config instance from which + required parameters can be taken. + :type build_config: :py:class:`fab.BuildConfig` + :param argparse.Namespace args: all command line options + ''' + + tr = ToolRepository() + ftn = tr.get_tool(Category.FORTRAN_COMPILER, "crayftn-ftn") + ftn = cast(Compiler, ftn) + + if not ftn.is_available: + return + + # The base flags + # ============== + flags = ["-g", "-G0", "-m", "0", # ? + "-M", "E664,E7208,E7212", # ? + "-en", # Fortran standard + "-ef", # use lowercase module names!Important! + "-hnocaf", # Required for linking with C++ + ] + + # Handle accelerator options: + if args.openacc or args.openmp: + host = args.host.lower() + else: + # Neither openacc nor openmp specified + host = "" + + if args.openacc: + if host == "gpu": + flags.extend(["-h acc"]) + else: + # CPU + flags.extend(["-h acc"]) + elif args.openmp: + if host == "gpu": + flags.extend([]) + else: + # OpenMP on CPU, that's already handled by Fab + pass + + ftn.add_flags(flags, "base") + + # Full debug + # ========== + ftn.add_flags(["-Ktrap=fp", # floating point checking + "-R", "bcdps", # bounds, array shape, collapse, + # pointer, string checking + "-O0"], # No optimisation + "full-debug") + if ftn.get_version() >= (15, 0): + ftn.add_flags(["-G0"], "full-debug") + else: + ftn.add_flags(["-Gfast"], "full-debug") + + # Fast debug + # ========== + ftn.add_flags(["-O2"], "fast-debug") + if ftn.get_version() >= (15, 0): + ftn.add_flags(["-G2"], "fast-debug") + else: + ftn.add_flags(["-Gfast"], "fast-debug") + + # Production + # ========== + ftn.add_flags(["-O3"], "production") + + # Set up the linker + # ================= + linker = tr.get_tool(Category.LINKER, "linker-crayftn-ftn") + linker = cast(Linker, linker) + + # ATM we don't use a shell when running a tool, and as such + # we can't directly use "$()" as parameter. So query these values using + # Fab's shell tool (doesn't really matter which shell we get, so just + # ask for the default): + shell = tr.get_default(Category.SHELL) + + try: + # We must remove the trailing new line, and create a list: + nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], + capture_output=True).strip().split() + except RuntimeError: + nc_flibs = [] + + linker.add_lib_flags("netcdf", nc_flibs) + linker.add_lib_flags("yaxt", ["-lyaxt", "-lyaxt_c"]) + linker.add_lib_flags("xios", ["-lxios"]) + linker.add_lib_flags("hdf5", ["-lhdf5"]) + + linker.add_post_lib_flags("-lcraystdc++") + + # Using the GNU compiler on Crays for now needs the additional + # flag -fallow-argument-mismatch to compile mpi_mod.f90 + ftn = tr.get_tool(Category.FORTRAN_COMPILER, "crayftn-gfortran") + ftn.add_flags("-fallow-argument-mismatch") diff --git a/fab/site_specific/default/setup_script_gnu.py b/fab/site_specific/default/setup_script_gnu.py new file mode 100644 index 00000000..318e2351 --- /dev/null +++ b/fab/site_specific/default/setup_script_gnu.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 + +'''This file contains a function that sets the default flags for all +GNU based compilers in the ToolRepository. + +This function gets called from the default site-specific config file +''' + +import argparse + +from typing import cast +from fab.api import BuildConfig, Category, Linker, ToolRepository + + +def setup_script_gnu(build_config: BuildConfig, args: argparse.Namespace): + # pylint: disable=unused-argument + '''Defines the default flags for all GNU compilers. + + :para build_config: the build config from which required parameters + can be taken. + :param args: all command line options + ''' + + tr = ToolRepository() + gfortran = tr.get_tool(Category.FORTRAN_COMPILER, "gfortran") + + if not gfortran.is_available: + gfortran = tr.get_tool(Category.FORTRAN_COMPILER, "mpif90-gfortran") + if not gfortran.is_available: + return + + # The base flags + # ============== + gfortran.add_flags( + ['-ffree-line-length-none', '-Wall', + '-g', + # TODO: Jules river cannot be compiled with this: + # '-Werror=unused-value', + # We might either try to fix the sources if possible, + # or see if it's worth setting this option only for one + # specific file (though that then means compiler-specific + # options in the generic fab script :( ) + '-Werror=tabs', + '-std=f2008', + ], + "base") + + if gfortran.get_version() >= (10, 0): + # Required for certain MPI versions (since gfortran version 10) + gfortran.add_flags("-fallow-argument-mismatch", "base") + + runtime = ["-fcheck=all", "-ffpe-trap=invalid,zero,overflow"] + init = ["-finit-integer=31173", "-finit-real=snan", + "-finit-logical=true", "-finit-character=85"] + # Full debug + # ========== + gfortran.add_flags(runtime + ["-O0"] + init, "full-debug") + + # Fast debug + # ========== + gfortran.add_flags(runtime + ["-Og"], "fast-debug") + + # Production + # ========== + gfortran.add_flags(["-Ofast"], "production") + + # unit-tests + # ========== + gfortran.add_flags(runtime + ["-O0"] + init, "unit-tests") + + # Set up the linker + # ================= + # This will implicitly affect all gfortran based linkers, e.g. + # linker-mpif90-gfortran will use these flags as well. + linker = tr.get_tool(Category.LINKER, "linker-gfortran") + linker = cast(Linker, linker) + + # ATM we don't use a shell when running a tool, and as such + # we can't directly use "$()" as parameter. So query these values using + # Fab's shell tool (doesn't really matter which shell we get, so just + # ask for the default): + shell = tr.get_default(Category.SHELL) + + try: + # We must remove the trailing new line, and create a list: + nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], + capture_output=True).strip().split() + except RuntimeError: + nc_flibs = [] + + linker.add_lib_flags("netcdf", nc_flibs) + linker.add_lib_flags("hdf5", ["-lhdf5"]) diff --git a/fab/site_specific/default/setup_script_intel_classic.py b/fab/site_specific/default/setup_script_intel_classic.py new file mode 100644 index 00000000..638e95cb --- /dev/null +++ b/fab/site_specific/default/setup_script_intel_classic.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 + +'''This file contains a function that sets the default flags for all +Intel classic based compilers in the ToolRepository (ifort, icc). + +This function gets called from the default site-specific config file +''' + +import argparse +from typing import cast + +from fab.api import BuildConfig, Category, Compiler, Linker, ToolRepository + + +def setup_script_intel_classic(build_config: BuildConfig, + args: argparse.Namespace): + # pylint: disable=unused-argument, too-many-locals + '''Defines the default flags for all Intel classic compilers. + + :para build_config: the build config from which required parameters + can be taken. + :param args: all command line options + ''' + + tr = ToolRepository() + ifort = tr.get_tool(Category.FORTRAN_COMPILER, "ifort") + ifort = cast(Compiler, ifort) + + if not ifort.is_available: + # This can happen if ifort is not in path (in spack environments). + # To support this common use case, see if mpif90-ifort is available, + # and initialise this otherwise. + ifort = tr.get_tool(Category.FORTRAN_COMPILER, "mpif90-ifort") + ifort = cast(Compiler, ifort) + if not ifort.is_available: + # Since some flags depends on version, the code below requires + # that the intel compiler actually works. + return + + # The base flags + # ============== + # The following flags will be applied to all modes: + ifort.add_flags(["-stand", "f08"], "base") + ifort.add_flags(["-g", "-traceback"], "base") + # With -warn errors we get externals that are too long. While this + # is a (usually safe) warning, the long externals then causes the + # build to abort. So for now we cannot use `-warn errors` + ifort.add_flags(["-warn", "all"], "base") + + # By default turning interface warnings on causes "genmod" files to be + # created. This adds unnecessary files to the build so we disable that + # behaviour. + ifort.add_flags(["-gen-interfaces", "nosource"], "base") + + # The "-assume realloc-lhs" switch causes Intel Fortran prior to v17 to + # actually implement the Fortran2003 standard. At version 17 it becomes the + # default behaviour. + if ifort.get_version() < (17, 0): + ifort.add_flags(["-assume", "realloc-lhs"], "base") + + # Full debug + # ========== + # ifort.mk: bad interaction between array shape checking and + # the matmul" intrinsic in at least some iterations of v19. + if (19, 0, 0) <= ifort.get_version() < (19, 1, 0): + runtime_flags = ["-check", "all,noshape", "-fpe0"] + else: + runtime_flags = ["-check", "all", "-fpe0"] + ifort.add_flags(runtime_flags, "full-debug") + ifort.add_flags(["-O0", "-ftrapuv"], "full-debug") + + # Fast debug + # ========== + ifort.add_flags(["-O2", "-fp-model=strict"], "fast-debug") + + # Production + # ========== + ifort.add_flags(["-O3", "-xhost"], "production") + + # Set up the linker + # ================= + # This will implicitly affect all ifort based linkers, e.g. + # linker-mpif90-ifort will use these flags as well. + linker = tr.get_tool(Category.LINKER, "linker-ifort") + linker = cast(Linker, linker) + + # ATM we don't use a shell when running a tool, and as such + # we can't directly use "$()" as parameter. So query these values using + # Fab's shell tool (doesn't really matter which shell we get, so just + # ask for the default): + shell = tr.get_default(Category.SHELL) + try: + # We must remove the trailing new line, and create a list: + nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], + capture_output=True).strip().split() + except RuntimeError: + nc_flibs = [] + + linker.add_lib_flags("netcdf", nc_flibs) + linker.add_lib_flags("yaxt", ["-lyaxt", "-lyaxt_c"]) + linker.add_lib_flags("xios", ["-lxios"]) + linker.add_lib_flags("hdf5", ["-lhdf5"]) + + # Always link with C++ libs + linker.add_post_lib_flags(["-lstdc++"]) diff --git a/fab/site_specific/default/setup_script_intel_llvm.py b/fab/site_specific/default/setup_script_intel_llvm.py new file mode 100644 index 00000000..a81b0474 --- /dev/null +++ b/fab/site_specific/default/setup_script_intel_llvm.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 + +'''This file contains a function that sets the default flags for all +Intel llvm based compilers in the ToolRepository (ifx, icx). + +This function gets called from the default site-specific config file +''' + +import argparse +from typing import cast + +from fab.api import BuildConfig, Category, Compiler, Linker, ToolRepository + + +def setup_script_intel_llvm(build_config: BuildConfig, + args: argparse.Namespace): + # pylint: disable=unused-argument, too-many-locals + '''Defines the default flags for all Intel llvm compilers. + + :para build_config: the build config from which required parameters + can be taken. + :param args: all command line options + ''' + + tr = ToolRepository() + ifx = tr.get_tool(Category.FORTRAN_COMPILER, "ifx") + ifx = cast(Compiler, ifx) + + if not ifx.is_available: + ifx = tr.get_tool(Category.FORTRAN_COMPILER, "mpif90-ifx") + ifx = cast(Compiler, ifx) + if not ifx.is_available: + return + + # The base flags + # ============== + # The following flags will be applied to all modes: + ifx.add_flags(["-stand", "f08"], "base") + ifx.add_flags(["-g", "-traceback"], "base") + # With -warn errors we get externals that are too long. While this + # is a (usually safe) warning, the long externals then causes the + # build to abort. So for now we cannot use `-warn errors` + ifx.add_flags(["-warn", "all"], "base") + + # By default turning interface warnings on causes "genmod" files to be + # created. This adds unnecessary files to the build so we disable that + # behaviour. + ifx.add_flags(["-gen-interfaces", "nosource"], "base") + + # Full debug + # ========== + ifx.add_flags(["-check", "all", "-fpe0"], "full-debug") + ifx.add_flags(["-O0", "-ftrapuv"], "full-debug") + + # Fast debug + # ========== + ifx.add_flags(["-O2", "-fp-model=strict"], "fast-debug") + + # Production + # ========== + ifx.add_flags(["-O3", "-xhost"], "production") + + # Set up the linker + # ================= + # This will implicitly affect all ifx based linkers, e.g. + # linker-mpif90-ifx will use these flags as well. + linker = tr.get_tool(Category.LINKER, "linker-ifx") + linker = cast(Linker, linker) # Make mypy happy + # ATM we don't use a shell when running a tool, and as such + # we can't directly use "$()" as parameter. So query these values using + # Fab's shell tool (doesn't really matter which shell we get, so just + # ask for the default): + shell = tr.get_default(Category.SHELL) + try: + # We must remove the trailing new line, and create a list: + nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], + capture_output=True).strip().split() + except RuntimeError: + nc_flibs = [] + + linker.add_lib_flags("netcdf", nc_flibs) + linker.add_lib_flags("yaxt", ["-lyaxt", "-lyaxt_c"]) + linker.add_lib_flags("xios", ["-lxios"]) + linker.add_lib_flags("hdf5", ["-lhdf5"]) + + # Always link with C++ libs + linker.add_post_lib_flags(["-lstdc++"]) diff --git a/fab/site_specific/default/setup_script_nvidia.py b/fab/site_specific/default/setup_script_nvidia.py new file mode 100644 index 00000000..f583d4ad --- /dev/null +++ b/fab/site_specific/default/setup_script_nvidia.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 + +'''This file contains a function that sets the default flags for the NVIDIA +compilers in the ToolRepository. + +This function gets called from the default site-specific config file +''' + +import argparse +from typing import cast + +from fab.api import BuildConfig, Category, Compiler, Linker, ToolRepository + + +def setup_script_nvidia(build_config: BuildConfig, args: argparse.Namespace): + # pylint: disable=unused-argument + '''Defines the default flags for nvfortran. + + :param build_config: the build config from which required parameters + can be taken. + :param args: all command line options + ''' + + tr = ToolRepository() + nvfortran = tr.get_tool(Category.FORTRAN_COMPILER, "nvfortran") + nvfortran = cast(Compiler, nvfortran) + + if not nvfortran.is_available: + nvfortran = tr.get_tool(Category.FORTRAN_COMPILER, "mpif90-nvfortran") + nvfortran = cast(Compiler, nvfortran) + if not nvfortran.is_available: + return + + # The base flags + # ============== + flags = ["-Mextend", # 132 characters line length + "-g", "-traceback", + "-r8", # Default 8 bytes reals + "-O0", # No optimisations + ] + + lib_flags = ["-c++libs"] + + # Handle accelerator options: + if args.openacc or args.openmp: + host = args.host.lower() + else: + # Neither openacc nor openmp specified + host = "" + + if args.openacc: + if host == "gpu": + flags.extend(["-acc=gpu", "-gpu=managed"]) + lib_flags.extend(["-aclibs", "-cuda"]) + else: + # CPU + flags.extend(["-acc=cpu"]) + elif args.openmp: + if host == "gpu": + flags.extend(["-mp=gpu", "-gpu=managed"]) + lib_flags.append("-cuda") + else: + # OpenMP on CPU, that's already handled by Fab + pass + + nvfortran.add_flags(flags, "base") + + # Full debug + # ========== + nvfortran.add_flags(["-O0", "-fp-model=strict"], "full-debug") + + # Fast debug + # ========== + nvfortran.add_flags(["-O2", "-fp-model=strict"], "fast-debug") + + # Production + # ========== + nvfortran.add_flags(["-O4"], "production") + + # Set up the linker + # ================= + # This will implicitly affect all nvfortran based linkers, e.g. + # linker-mpif90-nvfortran will use these flags as well. + linker = tr.get_tool(Category.LINKER, "linker-nvfortran") + linker = cast(Linker, linker) + + # ATM we don't use a shell when running a tool, and as such + # we can't directly use "$()" as parameter. So query these values using + # Fab's shell tool (doesn't really matter which shell we get, so just + # ask for the default): + shell = tr.get_default(Category.SHELL) + try: + # We must remove the trailing new line, and create a list: + nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], + capture_output=True).strip().split() + except RuntimeError: + nc_flibs = [] + + linker.add_lib_flags("netcdf", nc_flibs) + linker.add_lib_flags("yaxt", ["-lyaxt", "-lyaxt_c"]) + linker.add_lib_flags("xios", ["-lxios"]) + linker.add_lib_flags("hdf5", ["-lhdf5"]) + + # Always link with C++ libs + linker.add_post_lib_flags(lib_flags) From fb35985808fe391192b795527bd52a790d5b3d4f Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Mon, 17 Aug 2026 11:15:03 +1000 Subject: [PATCH 2/9] #102 Started to setup compiler-specific configurations. --- fab/fab_jules.py | 12 +- fab/nf_config.py | 37 ++++++ fab/site_specific/default/config.py | 24 ++-- .../default/setup_script_cray.py | 4 + fab/site_specific/default/setup_script_gnu.py | 85 ++++++------- .../default/setup_script_intel_classic.py | 80 +++++-------- .../default/setup_script_intel_llvm.py | 112 +++++++++--------- 7 files changed, 182 insertions(+), 172 deletions(-) create mode 100644 fab/nf_config.py diff --git a/fab/fab_jules.py b/fab/fab_jules.py index ff4bf06c..806d4c60 100755 --- a/fab/fab_jules.py +++ b/fab/fab_jules.py @@ -19,6 +19,8 @@ from fab.api import (FabBase, fcm_export, Exclude, find_source_files, git_checkout, Include, root_inc_files) +logger = logging.getLogger(__name__) + class JulesBuild(FabBase): ''' @@ -284,7 +286,7 @@ def get_linker_flags(self) -> list[str]: ''' libs = [] if not self._ascii_out: - libs.extend(["netcdf", "hdf5"]) + libs.extend(["netcdf"]) return libs @@ -298,15 +300,13 @@ class NoFabFilter(logging.Filter): def filter(self, record): return not record.name.startswith("fab") - root_logger = logging.getLogger() - root_logger.setLevel(logging.DEBUG) + # root_logger = logging.getLogger() + # root_logger.setLevel(logging.DEBUG) last_resort_handler = logging.lastResort last_resort_handler.setLevel(logging.DEBUG) - baf_logger = logging.getLogger("baf") - baf_logger.setLevel(logging.DEBUG) fab_logger = logging.getLogger("fab") - fab_logger.setLevel(logging.WARNING) + fab_logger.setLevel(logging.DEBUG) fab_handlers = fab_logger.handlers # fab_handlers[0].addFilter(NoFabFilter()) diff --git a/fab/nf_config.py b/fab/nf_config.py new file mode 100644 index 00000000..4d09c30e --- /dev/null +++ b/fab/nf_config.py @@ -0,0 +1,37 @@ +############################################################################## +# (c) Crown copyright Met Office. All rights reserved. +# For further details please refer to the file COPYRIGHT +# which you should have received as part of this distribution +############################################################################## + +"""This file contains the class to interface with NetCDF's nf-config script. +""" + +from typing import List + +from fab.tools.category import Category +from fab.tools.tool import Tool + + +class NfConfig(Tool): + '''This class interfaces with NetCDF's nf-config tool. It is not added + to the ToolRepository, it is intended for site-specific configurations + to make it easier to query for NetCDF settings. + ''' + + def __init__(self): + super().__init__("nf-config", "nf-config", Category.MISC) + + def get_compiler_flags(self) -> List[str]: + """ + :returns: the compilation flags to use for NetCDF. + """ + flags = self.run(additional_parameters=["--fflags"]) + return flags.split() + + def get_linker_flags(self) -> List[str]: + """ + :returns: the linker flags to use for NetCDF. + """ + flags = self.run(additional_parameters=["--flibs"]) + return flags.split() diff --git a/fab/site_specific/default/config.py b/fab/site_specific/default/config.py index b15f1a11..1f8c7eb7 100644 --- a/fab/site_specific/default/config.py +++ b/fab/site_specific/default/config.py @@ -10,11 +10,13 @@ from fab.api import BuildConfig, Category, ToolRepository -from default.setup_script_cray import setup_script_cray -from default.setup_script_gnu import setup_script_gnu -from default.setup_script_intel_classic import setup_script_intel_classic -from default.setup_script_intel_llvm import setup_script_intel_llvm -from default.setup_script_nvidia import setup_script_nvidia +from site_specific.default.setup_script_cray import setup_script_cray +from site_specific.default.setup_script_gnu import setup_script_gnu +from site_specific.default.setup_script_intel_classic import ( + setup_script_intel_classic) +from site_specific.default.setup_script_intel_llvm import ( + setup_script_intel_llvm) +from site_specific.default.setup_script_nvidia import setup_script_nvidia class Config: @@ -44,7 +46,7 @@ def get_valid_profiles(self) -> List[str]: :returns List[str]: list of all supported compiler profiles. ''' - return ["full-debug", "fast-debug", "production", "unit-tests"] + return ["debug", "normal", "fast"] def update_toolbox(self, build_config: BuildConfig) -> None: ''' @@ -55,13 +57,15 @@ def update_toolbox(self, build_config: BuildConfig) -> None: :type build_config: :py:class:`fab.BuildConfig` ''' # First create the default compiler profiles for all available - # compilers. While we have a tool box with exactly one compiler - # in it, compiler wrappers will require more than one compiler - # to be initialised - so we just initialise all of them (including - # the linker): + # compilers and preprocessor. While we have a tool box with exactly + # one compiler in it, compiler wrappers will require more than one + # compiler to be initialised - so we just initialise all of them + # (including the linker). Similarly, preprocessing might use + # profiles as well, so set them up: tr = ToolRepository() for compiler in (tr[Category.C_COMPILER] + tr[Category.FORTRAN_COMPILER] + + tr[Category.FORTRAN_PREPROCESSOR] + tr[Category.LINKER]): if compiler.is_available: # Define a base profile, which contains the common diff --git a/fab/site_specific/default/setup_script_cray.py b/fab/site_specific/default/setup_script_cray.py index f87a6509..68434f7f 100644 --- a/fab/site_specific/default/setup_script_cray.py +++ b/fab/site_specific/default/setup_script_cray.py @@ -24,6 +24,10 @@ def setup_script_cray(build_config: BuildConfig, args: argparse.Namespace): :param argparse.Namespace args: all command line options ''' + tb = build_config.tool_box + pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) + pre_fortran.add_flags("-DCRAY_FORTRAN") + tr = ToolRepository() ftn = tr.get_tool(Category.FORTRAN_COMPILER, "crayftn-ftn") ftn = cast(Compiler, ftn) diff --git a/fab/site_specific/default/setup_script_gnu.py b/fab/site_specific/default/setup_script_gnu.py index 318e2351..c9dbf9b8 100644 --- a/fab/site_specific/default/setup_script_gnu.py +++ b/fab/site_specific/default/setup_script_gnu.py @@ -9,7 +9,9 @@ import argparse from typing import cast -from fab.api import BuildConfig, Category, Linker, ToolRepository +from fab.api import BuildConfig, Category, ContainFlags, Linker, ToolRepository + +from nf_config import NfConfig def setup_script_gnu(build_config: BuildConfig, args: argparse.Namespace): @@ -21,6 +23,10 @@ def setup_script_gnu(build_config: BuildConfig, args: argparse.Namespace): :param args: all command line options ''' + tb = build_config.tool_box + pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) + pre_fortran.add_flags("-DGNU_FORTRAN") + tr = ToolRepository() gfortran = tr.get_tool(Category.FORTRAN_COMPILER, "gfortran") @@ -32,61 +38,46 @@ def setup_script_gnu(build_config: BuildConfig, args: argparse.Namespace): # The base flags # ============== gfortran.add_flags( - ['-ffree-line-length-none', '-Wall', - '-g', - # TODO: Jules river cannot be compiled with this: - # '-Werror=unused-value', - # We might either try to fix the sources if possible, - # or see if it's worth setting this option only for one - # specific file (though that then means compiler-specific - # options in the generic fab script :( ) - '-Werror=tabs', - '-std=f2008', - ], + ['-std=f2003', '-fall-intrinsics', '-fmax-identifier-length=63', + '-ffree-line-length-132', '-fimplicit-none', + '-Warray-bounds'], "base") if gfortran.get_version() >= (10, 0): # Required for certain MPI versions (since gfortran version 10) - gfortran.add_flags("-fallow-argument-mismatch", "base") + gfortran.add_flags( + ContainFlags("/read_dump_mod", "-fallow-argument-mismatch"), + "base") - runtime = ["-fcheck=all", "-ffpe-trap=invalid,zero,overflow"] - init = ["-finit-integer=31173", "-finit-real=snan", - "-finit-logical=true", "-finit-character=85"] - # Full debug - # ========== - gfortran.add_flags(runtime + ["-O0"] + init, "full-debug") + # Debug + # ===== + gfortran.add_flags(['-g', '-pg', '-ffpe-trap=invalid,zero,overflow', + '-fbacktrace', '-Wall', '-Wextra'], "debug") - # Fast debug - # ========== - gfortran.add_flags(runtime + ["-Og"], "fast-debug") + # Normal + # ====== + gfortran.add_flags(["-Werror"], "normal") - # Production - # ========== - gfortran.add_flags(["-Ofast"], "production") - - # unit-tests - # ========== - gfortran.add_flags(runtime + ["-O0"] + init, "unit-tests") + if gfortran.get_version() >= (10, 0): + # The -Werror flags turns the warning for argument mismatch back into + # an error, since this flag comes after -fallow-argument-mismatch + # (because "normal" in inherits from "base"). So, in case of normal + # compilation mode we need to disable -Werror for this one file: + gfortran.add_flags( + ContainFlags("/read_dump_mod", "-Wno-error"), + "normal") + # Fast + # ==== + gfortran.add_flags(["-O3"], "fast") # Set up the linker # ================= - # This will implicitly affect all gfortran based linkers, e.g. - # linker-mpif90-gfortran will use these flags as well. - linker = tr.get_tool(Category.LINKER, "linker-gfortran") + linker = tr.get_tool(Category.LINKER, f"linker-{gfortran.name}") linker = cast(Linker, linker) - # ATM we don't use a shell when running a tool, and as such - # we can't directly use "$()" as parameter. So query these values using - # Fab's shell tool (doesn't really matter which shell we get, so just - # ask for the default): - shell = tr.get_default(Category.SHELL) - - try: - # We must remove the trailing new line, and create a list: - nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], - capture_output=True).strip().split() - except RuntimeError: - nc_flibs = [] - - linker.add_lib_flags("netcdf", nc_flibs) - linker.add_lib_flags("hdf5", ["-lhdf5"]) + # As default, use nf-config to set NetCDF linker flags. If it's not + # available (or not working properly), the site-specific setup must + # add netcdf definitions. + nf_config = NfConfig() + if nf_config.is_available: + linker.add_lib_flags("netcdf", nf_config.get_linker_flags()) diff --git a/fab/site_specific/default/setup_script_intel_classic.py b/fab/site_specific/default/setup_script_intel_classic.py index 638e95cb..e00204a6 100644 --- a/fab/site_specific/default/setup_script_intel_classic.py +++ b/fab/site_specific/default/setup_script_intel_classic.py @@ -11,6 +11,8 @@ from fab.api import BuildConfig, Category, Compiler, Linker, ToolRepository +from nf_config import NfConfig + def setup_script_intel_classic(build_config: BuildConfig, args: argparse.Namespace): @@ -22,6 +24,10 @@ def setup_script_intel_classic(build_config: BuildConfig, :param args: all command line options ''' + tb = build_config.tool_box + pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) + pre_fortran.add_flags("-DINTEL_FORTRAN") + tr = ToolRepository() ifort = tr.get_tool(Category.FORTRAN_COMPILER, "ifort") ifort = cast(Compiler, ifort) @@ -40,42 +46,27 @@ def setup_script_intel_classic(build_config: BuildConfig, # The base flags # ============== # The following flags will be applied to all modes: - ifort.add_flags(["-stand", "f08"], "base") - ifort.add_flags(["-g", "-traceback"], "base") - # With -warn errors we get externals that are too long. While this - # is a (usually safe) warning, the long externals then causes the - # build to abort. So for now we cannot use `-warn errors` - ifort.add_flags(["-warn", "all"], "base") - - # By default turning interface warnings on causes "genmod" files to be - # created. This adds unnecessary files to the build so we disable that - # behaviour. - ifort.add_flags(["-gen-interfaces", "nosource"], "base") - - # The "-assume realloc-lhs" switch causes Intel Fortran prior to v17 to - # actually implement the Fortran2003 standard. At version 17 it becomes the - # default behaviour. - if ifort.get_version() < (17, 0): - ifort.add_flags(["-assume", "realloc-lhs"], "base") - - # Full debug - # ========== + common = ['-heap-arrays', '-std03', '-fpscomp', 'logicals', + # '-diag-disable', '6477', + '-traceback', + '-assume nosource_include,protect_parens', + '-fp-model', 'precise', '-no-vec'] + ifort.add_flags(common, "base") + + # Debug + # ===== # ifort.mk: bad interaction between array shape checking and # the matmul" intrinsic in at least some iterations of v19. - if (19, 0, 0) <= ifort.get_version() < (19, 1, 0): - runtime_flags = ["-check", "all,noshape", "-fpe0"] - else: - runtime_flags = ["-check", "all", "-fpe0"] - ifort.add_flags(runtime_flags, "full-debug") - ifort.add_flags(["-O0", "-ftrapuv"], "full-debug") + debug = ['-g', '-C', '-check', 'noarg_temp_created', '-fpe0', '-ftz', + '-ftrapuv', '-init=arrays'] + ifort.add_flags(debug, "debug") - # Fast debug - # ========== - ifort.add_flags(["-O2", "-fp-model=strict"], "fast-debug") + # Normal + # ====== - # Production - # ========== - ifort.add_flags(["-O3", "-xhost"], "production") + # Fast + # ==== + ifort.add_flags(["-O3"], "production") # Set up the linker # ================= @@ -84,22 +75,9 @@ def setup_script_intel_classic(build_config: BuildConfig, linker = tr.get_tool(Category.LINKER, "linker-ifort") linker = cast(Linker, linker) - # ATM we don't use a shell when running a tool, and as such - # we can't directly use "$()" as parameter. So query these values using - # Fab's shell tool (doesn't really matter which shell we get, so just - # ask for the default): - shell = tr.get_default(Category.SHELL) - try: - # We must remove the trailing new line, and create a list: - nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], - capture_output=True).strip().split() - except RuntimeError: - nc_flibs = [] - - linker.add_lib_flags("netcdf", nc_flibs) - linker.add_lib_flags("yaxt", ["-lyaxt", "-lyaxt_c"]) - linker.add_lib_flags("xios", ["-lxios"]) - linker.add_lib_flags("hdf5", ["-lhdf5"]) - - # Always link with C++ libs - linker.add_post_lib_flags(["-lstdc++"]) + # As default, use nf-config to set NetCDF linker flags. If it's not + # available (or not working properly), the site-specific setup must + # add netcdf definitions. + nf_config = NfConfig() + if nf_config.is_available: + linker.add_lib_flags("netcdf", nf_config.get_linker_flags()) diff --git a/fab/site_specific/default/setup_script_intel_llvm.py b/fab/site_specific/default/setup_script_intel_llvm.py index a81b0474..e00204a6 100644 --- a/fab/site_specific/default/setup_script_intel_llvm.py +++ b/fab/site_specific/default/setup_script_intel_llvm.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 '''This file contains a function that sets the default flags for all -Intel llvm based compilers in the ToolRepository (ifx, icx). +Intel classic based compilers in the ToolRepository (ifort, icc). This function gets called from the default site-specific config file ''' @@ -11,77 +11,73 @@ from fab.api import BuildConfig, Category, Compiler, Linker, ToolRepository +from nf_config import NfConfig -def setup_script_intel_llvm(build_config: BuildConfig, - args: argparse.Namespace): + +def setup_script_intel_classic(build_config: BuildConfig, + args: argparse.Namespace): # pylint: disable=unused-argument, too-many-locals - '''Defines the default flags for all Intel llvm compilers. + '''Defines the default flags for all Intel classic compilers. :para build_config: the build config from which required parameters can be taken. :param args: all command line options ''' - tr = ToolRepository() - ifx = tr.get_tool(Category.FORTRAN_COMPILER, "ifx") - ifx = cast(Compiler, ifx) + tb = build_config.tool_box + pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) + pre_fortran.add_flags("-DINTEL_FORTRAN") - if not ifx.is_available: - ifx = tr.get_tool(Category.FORTRAN_COMPILER, "mpif90-ifx") - ifx = cast(Compiler, ifx) - if not ifx.is_available: + tr = ToolRepository() + ifort = tr.get_tool(Category.FORTRAN_COMPILER, "ifort") + ifort = cast(Compiler, ifort) + + if not ifort.is_available: + # This can happen if ifort is not in path (in spack environments). + # To support this common use case, see if mpif90-ifort is available, + # and initialise this otherwise. + ifort = tr.get_tool(Category.FORTRAN_COMPILER, "mpif90-ifort") + ifort = cast(Compiler, ifort) + if not ifort.is_available: + # Since some flags depends on version, the code below requires + # that the intel compiler actually works. return # The base flags # ============== # The following flags will be applied to all modes: - ifx.add_flags(["-stand", "f08"], "base") - ifx.add_flags(["-g", "-traceback"], "base") - # With -warn errors we get externals that are too long. While this - # is a (usually safe) warning, the long externals then causes the - # build to abort. So for now we cannot use `-warn errors` - ifx.add_flags(["-warn", "all"], "base") - - # By default turning interface warnings on causes "genmod" files to be - # created. This adds unnecessary files to the build so we disable that - # behaviour. - ifx.add_flags(["-gen-interfaces", "nosource"], "base") - - # Full debug - # ========== - ifx.add_flags(["-check", "all", "-fpe0"], "full-debug") - ifx.add_flags(["-O0", "-ftrapuv"], "full-debug") - - # Fast debug - # ========== - ifx.add_flags(["-O2", "-fp-model=strict"], "fast-debug") - - # Production - # ========== - ifx.add_flags(["-O3", "-xhost"], "production") + common = ['-heap-arrays', '-std03', '-fpscomp', 'logicals', + # '-diag-disable', '6477', + '-traceback', + '-assume nosource_include,protect_parens', + '-fp-model', 'precise', '-no-vec'] + ifort.add_flags(common, "base") + + # Debug + # ===== + # ifort.mk: bad interaction between array shape checking and + # the matmul" intrinsic in at least some iterations of v19. + debug = ['-g', '-C', '-check', 'noarg_temp_created', '-fpe0', '-ftz', + '-ftrapuv', '-init=arrays'] + ifort.add_flags(debug, "debug") + + # Normal + # ====== + + # Fast + # ==== + ifort.add_flags(["-O3"], "production") # Set up the linker # ================= - # This will implicitly affect all ifx based linkers, e.g. - # linker-mpif90-ifx will use these flags as well. - linker = tr.get_tool(Category.LINKER, "linker-ifx") - linker = cast(Linker, linker) # Make mypy happy - # ATM we don't use a shell when running a tool, and as such - # we can't directly use "$()" as parameter. So query these values using - # Fab's shell tool (doesn't really matter which shell we get, so just - # ask for the default): - shell = tr.get_default(Category.SHELL) - try: - # We must remove the trailing new line, and create a list: - nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], - capture_output=True).strip().split() - except RuntimeError: - nc_flibs = [] - - linker.add_lib_flags("netcdf", nc_flibs) - linker.add_lib_flags("yaxt", ["-lyaxt", "-lyaxt_c"]) - linker.add_lib_flags("xios", ["-lxios"]) - linker.add_lib_flags("hdf5", ["-lhdf5"]) - - # Always link with C++ libs - linker.add_post_lib_flags(["-lstdc++"]) + # This will implicitly affect all ifort based linkers, e.g. + # linker-mpif90-ifort will use these flags as well. + linker = tr.get_tool(Category.LINKER, "linker-ifort") + linker = cast(Linker, linker) + + # As default, use nf-config to set NetCDF linker flags. If it's not + # available (or not working properly), the site-specific setup must + # add netcdf definitions. + nf_config = NfConfig() + if nf_config.is_available: + linker.add_lib_flags("netcdf", nf_config.get_linker_flags()) From 86699310989f5006ca34db14c9573be022332d8c Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Mon, 17 Aug 2026 11:40:02 +1000 Subject: [PATCH 3/9] #102 Fixed for intel compiler. --- fab/site_specific/default/setup_script_intel_classic.py | 2 +- fab/site_specific/default/setup_script_intel_llvm.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fab/site_specific/default/setup_script_intel_classic.py b/fab/site_specific/default/setup_script_intel_classic.py index e00204a6..8a509bf4 100644 --- a/fab/site_specific/default/setup_script_intel_classic.py +++ b/fab/site_specific/default/setup_script_intel_classic.py @@ -66,7 +66,7 @@ def setup_script_intel_classic(build_config: BuildConfig, # Fast # ==== - ifort.add_flags(["-O3"], "production") + ifort.add_flags(["-O3"], "fast") # Set up the linker # ================= diff --git a/fab/site_specific/default/setup_script_intel_llvm.py b/fab/site_specific/default/setup_script_intel_llvm.py index e00204a6..3bd37f0e 100644 --- a/fab/site_specific/default/setup_script_intel_llvm.py +++ b/fab/site_specific/default/setup_script_intel_llvm.py @@ -14,10 +14,10 @@ from nf_config import NfConfig -def setup_script_intel_classic(build_config: BuildConfig, +def setup_script_intel_llvm(build_config: BuildConfig, args: argparse.Namespace): # pylint: disable=unused-argument, too-many-locals - '''Defines the default flags for all Intel classic compilers. + '''Defines the default flags for all Intel llvm compilers. :para build_config: the build config from which required parameters can be taken. @@ -66,7 +66,7 @@ def setup_script_intel_classic(build_config: BuildConfig, # Fast # ==== - ifort.add_flags(["-O3"], "production") + ifort.add_flags(["-O3"], "fast") # Set up the linker # ================= From 788c78953dda944338f6a56d81d9d1f51f0c09e0 Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Mon, 17 Aug 2026 14:42:30 +1000 Subject: [PATCH 4/9] #102 Make sure only one compiler-specific flag is set. --- fab/site_specific/default/config.py | 11 +++++++++++ fab/site_specific/default/setup_script_cray.py | 4 ---- fab/site_specific/default/setup_script_gnu.py | 4 ---- .../default/setup_script_intel_classic.py | 7 ------- fab/site_specific/default/setup_script_intel_llvm.py | 9 +-------- 5 files changed, 12 insertions(+), 23 deletions(-) diff --git a/fab/site_specific/default/config.py b/fab/site_specific/default/config.py index 1f8c7eb7..9a555f87 100644 --- a/fab/site_specific/default/config.py +++ b/fab/site_specific/default/config.py @@ -83,6 +83,17 @@ def update_toolbox(self, build_config: BuildConfig) -> None: self.setup_nvidia(build_config) self.setup_cray(build_config) + # Define compiler-specific preprocessing flag + tb = build_config.tool_box + fortran = tb.get_tool(Category.FORTRAN_COMPILER) + pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) + if fortran.suite == "gnu": + pre_fortran.add_flags("-DGNU_FORTRAN") + elif fortran.suite in ["intel-classic", "intel-llvm"]: + pre_fortran.add_flags("-DINTEL_FORTRAN") + elif fortran.suite in ["cray"]: + pre_fortran.add_flags("-DCRAY_FORTRAN") + def handle_command_line_options(self, args: argparse.Namespace) -> None: ''' Additional callback function executed once all command line diff --git a/fab/site_specific/default/setup_script_cray.py b/fab/site_specific/default/setup_script_cray.py index 68434f7f..f87a6509 100644 --- a/fab/site_specific/default/setup_script_cray.py +++ b/fab/site_specific/default/setup_script_cray.py @@ -24,10 +24,6 @@ def setup_script_cray(build_config: BuildConfig, args: argparse.Namespace): :param argparse.Namespace args: all command line options ''' - tb = build_config.tool_box - pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) - pre_fortran.add_flags("-DCRAY_FORTRAN") - tr = ToolRepository() ftn = tr.get_tool(Category.FORTRAN_COMPILER, "crayftn-ftn") ftn = cast(Compiler, ftn) diff --git a/fab/site_specific/default/setup_script_gnu.py b/fab/site_specific/default/setup_script_gnu.py index c9dbf9b8..743f1c44 100644 --- a/fab/site_specific/default/setup_script_gnu.py +++ b/fab/site_specific/default/setup_script_gnu.py @@ -23,10 +23,6 @@ def setup_script_gnu(build_config: BuildConfig, args: argparse.Namespace): :param args: all command line options ''' - tb = build_config.tool_box - pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) - pre_fortran.add_flags("-DGNU_FORTRAN") - tr = ToolRepository() gfortran = tr.get_tool(Category.FORTRAN_COMPILER, "gfortran") diff --git a/fab/site_specific/default/setup_script_intel_classic.py b/fab/site_specific/default/setup_script_intel_classic.py index 8a509bf4..63df1a6f 100644 --- a/fab/site_specific/default/setup_script_intel_classic.py +++ b/fab/site_specific/default/setup_script_intel_classic.py @@ -24,10 +24,6 @@ def setup_script_intel_classic(build_config: BuildConfig, :param args: all command line options ''' - tb = build_config.tool_box - pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) - pre_fortran.add_flags("-DINTEL_FORTRAN") - tr = ToolRepository() ifort = tr.get_tool(Category.FORTRAN_COMPILER, "ifort") ifort = cast(Compiler, ifort) @@ -47,7 +43,6 @@ def setup_script_intel_classic(build_config: BuildConfig, # ============== # The following flags will be applied to all modes: common = ['-heap-arrays', '-std03', '-fpscomp', 'logicals', - # '-diag-disable', '6477', '-traceback', '-assume nosource_include,protect_parens', '-fp-model', 'precise', '-no-vec'] @@ -55,8 +50,6 @@ def setup_script_intel_classic(build_config: BuildConfig, # Debug # ===== - # ifort.mk: bad interaction between array shape checking and - # the matmul" intrinsic in at least some iterations of v19. debug = ['-g', '-C', '-check', 'noarg_temp_created', '-fpe0', '-ftz', '-ftrapuv', '-init=arrays'] ifort.add_flags(debug, "debug") diff --git a/fab/site_specific/default/setup_script_intel_llvm.py b/fab/site_specific/default/setup_script_intel_llvm.py index 3bd37f0e..b63bdc19 100644 --- a/fab/site_specific/default/setup_script_intel_llvm.py +++ b/fab/site_specific/default/setup_script_intel_llvm.py @@ -15,7 +15,7 @@ def setup_script_intel_llvm(build_config: BuildConfig, - args: argparse.Namespace): + args: argparse.Namespace): # pylint: disable=unused-argument, too-many-locals '''Defines the default flags for all Intel llvm compilers. @@ -24,10 +24,6 @@ def setup_script_intel_llvm(build_config: BuildConfig, :param args: all command line options ''' - tb = build_config.tool_box - pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) - pre_fortran.add_flags("-DINTEL_FORTRAN") - tr = ToolRepository() ifort = tr.get_tool(Category.FORTRAN_COMPILER, "ifort") ifort = cast(Compiler, ifort) @@ -47,7 +43,6 @@ def setup_script_intel_llvm(build_config: BuildConfig, # ============== # The following flags will be applied to all modes: common = ['-heap-arrays', '-std03', '-fpscomp', 'logicals', - # '-diag-disable', '6477', '-traceback', '-assume nosource_include,protect_parens', '-fp-model', 'precise', '-no-vec'] @@ -55,8 +50,6 @@ def setup_script_intel_llvm(build_config: BuildConfig, # Debug # ===== - # ifort.mk: bad interaction between array shape checking and - # the matmul" intrinsic in at least some iterations of v19. debug = ['-g', '-C', '-check', 'noarg_temp_created', '-fpe0', '-ftz', '-ftrapuv', '-init=arrays'] ifort.add_flags(debug, "debug") From e334dbffa295d248877b373564700cb81a0bd6ad Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Mon, 17 Aug 2026 14:46:25 +1000 Subject: [PATCH 5/9] #102 Moved setting of compiler preprocessor define into the fab script itself. --- fab/fab_jules.py | 14 +++++++++++++- fab/site_specific/default/config.py | 11 ----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/fab/fab_jules.py b/fab/fab_jules.py index 806d4c60..6c5a2318 100755 --- a/fab/fab_jules.py +++ b/fab/fab_jules.py @@ -16,7 +16,7 @@ from typing import cast, Iterable, Optional, Union -from fab.api import (FabBase, fcm_export, Exclude, find_source_files, +from fab.api import (Category, FabBase, fcm_export, Exclude, find_source_files, git_checkout, Include, root_inc_files) logger = logging.getLogger(__name__) @@ -271,6 +271,18 @@ def define_preprocessor_flags_step(self) -> None: Defines the preprocessor flags. ''' super().define_preprocessor_flags_step() + + # Define compiler-specific preprocessing flag + tb = self.config.tool_box + fortran = tb.get_tool(Category.FORTRAN_COMPILER) + pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) + if fortran.suite == "gnu": + pre_fortran.add_flags("-DGNU_FORTRAN") + elif fortran.suite in ["intel-classic", "intel-llvm"]: + pre_fortran.add_flags("-DINTEL_FORTRAN") + elif fortran.suite in ["cray"]: + pre_fortran.add_flags("-DCRAY_FORTRAN") + flags = ["-I$output"] if not self.config.mpi: flags.append("-DMPI_DUMMY") diff --git a/fab/site_specific/default/config.py b/fab/site_specific/default/config.py index 9a555f87..1f8c7eb7 100644 --- a/fab/site_specific/default/config.py +++ b/fab/site_specific/default/config.py @@ -83,17 +83,6 @@ def update_toolbox(self, build_config: BuildConfig) -> None: self.setup_nvidia(build_config) self.setup_cray(build_config) - # Define compiler-specific preprocessing flag - tb = build_config.tool_box - fortran = tb.get_tool(Category.FORTRAN_COMPILER) - pre_fortran = tb.get_tool(Category.FORTRAN_PREPROCESSOR) - if fortran.suite == "gnu": - pre_fortran.add_flags("-DGNU_FORTRAN") - elif fortran.suite in ["intel-classic", "intel-llvm"]: - pre_fortran.add_flags("-DINTEL_FORTRAN") - elif fortran.suite in ["cray"]: - pre_fortran.add_flags("-DCRAY_FORTRAN") - def handle_command_line_options(self, args: argparse.Namespace) -> None: ''' Additional callback function executed once all command line From 61d3291461a5b9bd6eb2d64af732ca827eb80fe0 Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Mon, 17 Aug 2026 16:04:30 +1000 Subject: [PATCH 6/9] #102 Updated Cray flags. --- .../default/setup_script_cray.py | 99 ++++++------------- 1 file changed, 29 insertions(+), 70 deletions(-) diff --git a/fab/site_specific/default/setup_script_cray.py b/fab/site_specific/default/setup_script_cray.py index f87a6509..fb8adbf4 100644 --- a/fab/site_specific/default/setup_script_cray.py +++ b/fab/site_specific/default/setup_script_cray.py @@ -10,7 +10,10 @@ import argparse from typing import cast -from fab.api import BuildConfig, Category, Compiler, Linker, ToolRepository +from fab.api import (BuildConfig, Category, ContainFlags, Compiler, Linker, + ToolRepository) + +from nf_config import NfConfig def setup_script_cray(build_config: BuildConfig, args: argparse.Namespace): @@ -33,54 +36,28 @@ def setup_script_cray(build_config: BuildConfig, args: argparse.Namespace): # The base flags # ============== - flags = ["-g", "-G0", "-m", "0", # ? - "-M", "E664,E7208,E7212", # ? - "-en", # Fortran standard - "-ef", # use lowercase module names!Important! - "-hnocaf", # Required for linking with C++ - ] - - # Handle accelerator options: - if args.openacc or args.openmp: - host = args.host.lower() - else: - # Neither openacc nor openmp specified - host = "" - - if args.openacc: - if host == "gpu": - flags.extend(["-h acc"]) - else: - # CPU - flags.extend(["-h acc"]) - elif args.openmp: - if host == "gpu": - flags.extend([]) - else: - # OpenMP on CPU, that's already handled by Fab - pass + flags = ['-M E7208,E7212', # Var used before defined + '-hlist=ad', '-hfp0', '-hflex_mp=intolerant', + '-dw', '-ec', '-eI', '-em', '-en'] ftn.add_flags(flags, "base") - # Full debug - # ========== - ftn.add_flags(["-Ktrap=fp", # floating point checking - "-R", "bcdps", # bounds, array shape, collapse, - # pointer, string checking - "-O0"], # No optimisation - "full-debug") - if ftn.get_version() >= (15, 0): - ftn.add_flags(["-G0"], "full-debug") - else: - ftn.add_flags(["-Gfast"], "full-debug") - - # Fast debug - # ========== - ftn.add_flags(["-O2"], "fast-debug") - if ftn.get_version() >= (15, 0): - ftn.add_flags(["-G2"], "fast-debug") - else: - ftn.add_flags(["-Gfast"], "fast-debug") + # File override to cut down compile times - compiler version: cce/12.0.1 + if (12, 0, 1) <= ftn.get_version() < (12, 1): + # Setting this for all modes + ftn.add_flags(ContainFlags("/model_interface_mod.", + ['-O0', '-Ovector0', '-hfp0', + '-hflex_mp=strict', '-hipa0']), + "base") + ftn.add_flags(ContainFlags("/init_prescribed_data.", ['-O1']), + "base") + + # Debug + # ===== + ftn.add_flags(["-g"], "debug") + + # Normal + # ====== # Production # ========== @@ -91,27 +68,9 @@ def setup_script_cray(build_config: BuildConfig, args: argparse.Namespace): linker = tr.get_tool(Category.LINKER, "linker-crayftn-ftn") linker = cast(Linker, linker) - # ATM we don't use a shell when running a tool, and as such - # we can't directly use "$()" as parameter. So query these values using - # Fab's shell tool (doesn't really matter which shell we get, so just - # ask for the default): - shell = tr.get_default(Category.SHELL) - - try: - # We must remove the trailing new line, and create a list: - nc_flibs = shell.run(additional_parameters=["-c", "nf-config --flibs"], - capture_output=True).strip().split() - except RuntimeError: - nc_flibs = [] - - linker.add_lib_flags("netcdf", nc_flibs) - linker.add_lib_flags("yaxt", ["-lyaxt", "-lyaxt_c"]) - linker.add_lib_flags("xios", ["-lxios"]) - linker.add_lib_flags("hdf5", ["-lhdf5"]) - - linker.add_post_lib_flags("-lcraystdc++") - - # Using the GNU compiler on Crays for now needs the additional - # flag -fallow-argument-mismatch to compile mpi_mod.f90 - ftn = tr.get_tool(Category.FORTRAN_COMPILER, "crayftn-gfortran") - ftn.add_flags("-fallow-argument-mismatch") + # As default, use nf-config to set NetCDF linker flags. If it's not + # available (or not working properly), the site-specific setup must + # add netcdf definitions. + nf_config = NfConfig() + if nf_config.is_available: + linker.add_lib_flags("netcdf", nf_config.get_linker_flags()) From fa7d572c60195bf5a0add230fc458c294a32f6b1 Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Tue, 18 Aug 2026 10:54:50 +1000 Subject: [PATCH 7/9] #102 Fixed ifx setting. --- .../default/setup_script_intel_llvm.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/fab/site_specific/default/setup_script_intel_llvm.py b/fab/site_specific/default/setup_script_intel_llvm.py index b63bdc19..a283aca3 100644 --- a/fab/site_specific/default/setup_script_intel_llvm.py +++ b/fab/site_specific/default/setup_script_intel_llvm.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 '''This file contains a function that sets the default flags for all -Intel classic based compilers in the ToolRepository (ifort, icc). +Intel classic based compilers in the ToolRepository (ifx, icx). This function gets called from the default site-specific config file ''' @@ -25,16 +25,16 @@ def setup_script_intel_llvm(build_config: BuildConfig, ''' tr = ToolRepository() - ifort = tr.get_tool(Category.FORTRAN_COMPILER, "ifort") - ifort = cast(Compiler, ifort) + ifx = tr.get_tool(Category.FORTRAN_COMPILER, "ifx") + ifx = cast(Compiler, ifx) - if not ifort.is_available: - # This can happen if ifort is not in path (in spack environments). - # To support this common use case, see if mpif90-ifort is available, + if not ifx.is_available: + # This can happen if ifx is not in path (in spack environments). + # To support this common use case, see if mpif90-ifx is available, # and initialise this otherwise. - ifort = tr.get_tool(Category.FORTRAN_COMPILER, "mpif90-ifort") - ifort = cast(Compiler, ifort) - if not ifort.is_available: + ifx = tr.get_tool(Category.FORTRAN_COMPILER, "mpif90-ifx") + ifx = cast(Compiler, ifx) + if not ifx.is_available: # Since some flags depends on version, the code below requires # that the intel compiler actually works. return @@ -46,26 +46,26 @@ def setup_script_intel_llvm(build_config: BuildConfig, '-traceback', '-assume nosource_include,protect_parens', '-fp-model', 'precise', '-no-vec'] - ifort.add_flags(common, "base") + ifx.add_flags(common, "base") # Debug # ===== debug = ['-g', '-C', '-check', 'noarg_temp_created', '-fpe0', '-ftz', '-ftrapuv', '-init=arrays'] - ifort.add_flags(debug, "debug") + ifx.add_flags(debug, "debug") # Normal # ====== # Fast # ==== - ifort.add_flags(["-O3"], "fast") + ifx.add_flags(["-O3"], "fast") # Set up the linker # ================= - # This will implicitly affect all ifort based linkers, e.g. - # linker-mpif90-ifort will use these flags as well. - linker = tr.get_tool(Category.LINKER, "linker-ifort") + # This will implicitly affect all ifx based linkers, e.g. + # linker-mpif90-ifx will use these flags as well. + linker = tr.get_tool(Category.LINKER, "linker-ifx") linker = cast(Linker, linker) # As default, use nf-config to set NetCDF linker flags. If it's not From 92da57960d8c11dd1c4964b28a605810fbe0ee66 Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Tue, 18 Aug 2026 23:11:18 +1000 Subject: [PATCH 8/9] #102 Updated CONTRIBUTORS. --- CONTRIBUTORS.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index db1cc110..254e91f4 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,7 +1,8 @@ # Contributors -| GitHub user | Real Name | Affiliation | Date | -| --------------- | ---------------- | ----------- | ---------- | -| yaswant | Yaswant Pradhan | Met Office | 2026-06-30 | -| doucla | Douglas Clark | UKCEH | 2026-07-03 | -| james-bruten-mo | James Bruten | Met Office | 2026-07-09 | +| GitHub user | Real Name | Affiliation | Date | +| --------------- | ---------------- | -------------------------------- | ---------- | +| yaswant | Yaswant Pradhan | Met Office | 2026-06-30 | +| doucla | Douglas Clark | UKCEH | 2026-07-03 | +| james-bruten-mo | James Bruten | Met Office | 2026-07-09 | +| hiker | Joerg Henrichs | Bureau of Meteorology, Australia | 2026-08-18 | From 8af677dbce7d5cb18fda6798b84e7e62783269dc Mon Sep 17 00:00:00 2001 From: Joerg Henrichs Date: Thu, 27 Aug 2026 16:24:14 +1000 Subject: [PATCH 9/9] #102 Use simplified compilation profile definition. --- fab/site_specific/default/config.py | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/fab/site_specific/default/config.py b/fab/site_specific/default/config.py index 1f8c7eb7..f0da4820 100644 --- a/fab/site_specific/default/config.py +++ b/fab/site_specific/default/config.py @@ -8,7 +8,7 @@ import argparse from typing import List -from fab.api import BuildConfig, Category, ToolRepository +from fab.api import BuildConfig, ProfileFlags from site_specific.default.setup_script_cray import setup_script_cray from site_specific.default.setup_script_gnu import setup_script_gnu @@ -56,26 +56,13 @@ def update_toolbox(self, build_config: BuildConfig) -> None: :param build_config: the Fab build configuration instance :type build_config: :py:class:`fab.BuildConfig` ''' - # First create the default compiler profiles for all available - # compilers and preprocessor. While we have a tool box with exactly - # one compiler in it, compiler wrappers will require more than one - # compiler to be initialised - so we just initialise all of them - # (including the linker). Similarly, preprocessing might use - # profiles as well, so set them up: - tr = ToolRepository() - for compiler in (tr[Category.C_COMPILER] + - tr[Category.FORTRAN_COMPILER] + - tr[Category.FORTRAN_PREPROCESSOR] + - tr[Category.LINKER]): - if compiler.is_available: - # Define a base profile, which contains the common - # compilation flags. This 'base' is not accessible to - # the user, so it's not part of the profile list. Also, - # make it inherit from the default profile '', so that - # a user does not have to specify the base profile - compiler.define_profile("base", inherit_from="") - for profile in self.get_valid_profiles(): - compiler.define_profile(profile, inherit_from="base") + # First create the default compiler profiles + # Define a base profile, which contains the common + # compilation flags. This 'base' is not accessible to + # the user, so it's not part of the profile list. + ProfileFlags.define_profile("base") + for profile in self.get_valid_profiles(): + ProfileFlags.define_profile(profile, inherit_from="base") self.setup_intel_classic(build_config) self.setup_intel_llvm(build_config)