-
Notifications
You must be signed in to change notification settings - Fork 39
240 add skeleton fab script #246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4dbac71
2254b31
c1e87d1
a350ef3
962ce0a
54491da
22c2ef9
25c26fb
72192df
f7a839c
170cab3
d7aa9f1
2315007
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,15 +1,17 @@ | ||
| # Contributors | ||
| | GitHub user | Real Name | Affiliation | Date | | ||
| | --------------- | ---------------- | ----------- | ---------- | | ||
| | andrewcoughtrie | Andrew Coughtrie | Met Office | 2025.12.12 | | ||
| | james-bruten-mo | James Bruten | Met Office | 2025-12-09 | | ||
| | jedbakerMO | Jed Baker | Met Office | 2025-12-29 | | ||
| | jennyhickson | Jenny Hickson | Met Office | 2025-12-10 | | ||
| | mo-marqh | Mark Hedley | Met Office | 2025-12-11 | | ||
| | mike-hobson | Mike Hobson | Met Office | 2025-12-17 | | ||
| | MatthewHambley | Matthew Hambley | Met Office | 2025-12-15 | | ||
| | yaswant | Yaswant Pradhan | Met Office | 2025-12-16 | | ||
| | stevemullerworth | Steve Mullerworth | Met Office | 2026-01-08 | | ||
| | harry-shepherd | Harry Shepherd | Met Office | 2026-01-08 | | ||
| | EdHone | Ed Hone | Met Office | 2026-01-09 | | ||
| | tom-j-h | Tom Hill | Met Office | 2026-01-19 | | ||
|
|
||
| | GitHub user | Real Name | Affiliation | Date | | ||
| | ---------------- | ----------------- | --------------------- | ---------- | | ||
| | andrewcoughtrie | Andrew Coughtrie | Met Office | 2025.12.12 | | ||
| | james-bruten-mo | James Bruten | Met Office | 2025-12-09 | | ||
| | jedbakerMO | Jed Baker | Met Office | 2025-12-29 | | ||
| | jennyhickson | Jenny Hickson | Met Office | 2025-12-10 | | ||
| | mo-marqh | Mark Hedley | Met Office | 2025-12-11 | | ||
| | mike-hobson | Mike Hobson | Met Office | 2025-12-17 | | ||
| | MatthewHambley | Matthew Hambley | Met Office | 2025-12-15 | | ||
| | yaswant | Yaswant Pradhan | Met Office | 2025-12-16 | | ||
| | stevemullerworth | Steve Mullerworth | Met Office | 2026-01-08 | | ||
| | harry-shepherd | Harry Shepherd | Met Office | 2026-01-08 | | ||
| | EdHone | Ed Hone | Met Office | 2026-01-09 | | ||
| | tom-j-h | Tom Hill | Met Office | 2026-01-19 | | ||
| | hiker | Joerg Henrichs | Bureau of Meteorology | 2026-01-22 | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| ############################################################################## | ||
| # (c) Crown copyright Met Office. All rights reserved. | ||
| # The file LICENCE, distributed with this code, contains details of the terms | ||
| # under which the code may be used. | ||
| ############################################################################## | ||
| # Author: J. Henrichs, Bureau of Meteorology | ||
| # Author: J. Lyu, Bureau of Meteorology | ||
|
|
||
| """ | ||
| A FAB build script for applications/skeleton. It relies on | ||
| the LFRicBase class contained in the infrastructure directory. | ||
| """ | ||
|
|
||
| import logging | ||
| from pathlib import Path | ||
| import sys | ||
|
|
||
| from fab.steps.grab.folder import grab_folder | ||
|
|
||
| # We need to import the base class: | ||
| sys.path.insert(0, str(Path(__file__).parents[2] / "infrastructure" / | ||
| "build" / "fab")) | ||
|
|
||
| from lfric_base import LFRicBase # noqa: E402 | ||
|
|
||
|
|
||
| class FabSkeleton(LFRicBase): | ||
| """ | ||
| A Fab-based build script for skeleton. It relies on the LFRicBase class | ||
| to implement the actual functionality, and only provides the required | ||
| source files. | ||
|
|
||
| :param name: The name of the application. | ||
| """ | ||
|
|
||
| def __init__(self, name: str) -> None: | ||
| super().__init__(name=name) | ||
| # Store the root of this apps for later | ||
| this_file = Path(__file__).resolve() | ||
| self._this_root = this_file.parent | ||
|
|
||
| def grab_files_step(self) -> None: | ||
| """ | ||
| Grabs the required source files and optimisation scripts. | ||
| """ | ||
| super().grab_files_step() | ||
| dirs = ['applications/skeleton/source/'] | ||
|
|
||
| # pylint: disable=redefined-builtin | ||
| for dir in dirs: | ||
| grab_folder(self.config, src=self.lfric_core_root / dir, | ||
| dst_label='') | ||
|
|
||
| # Copy the optimisation scripts into a separate directory | ||
| grab_folder(self.config, src=self._this_root / "optimisation", | ||
| dst_label='optimisation') | ||
|
|
||
| def get_rose_meta(self) -> Path: | ||
| """ | ||
| :returns: the rose-meta.conf path. | ||
| """ | ||
| return (self._this_root / 'rose-meta' / 'lfric-skeleton' / 'HEAD' / | ||
| 'rose-meta.conf') | ||
|
|
||
|
|
||
| # ----------------------------------------------------------------------------- | ||
| if __name__ == '__main__': | ||
|
|
||
| logger = logging.getLogger('fab') | ||
| logger.setLevel(logging.DEBUG) | ||
| fab_skeleton = FabSkeleton(name="skeleton") | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I notice that the build executable implements a class named after the project being built yet that class is passed the project name on initialisation. Why not pass that name from the constructor? class ProjectBuild(LFRicBase):
def __init__(self):
super().__init__(name="project")
if __name__ == '__main__':
builder = ProjectBuild() |
||
| fab_skeleton.build() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generic build components should be in lfric_build at the top level, not infrastructure/build. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # LFRic Core Fab Build Scripts | ||
|
|
||
| Make sure you have Fab version 2.0.1 or later installed (in addition to all | ||
| LFRic core requirements of course). | ||
|
|
||
| ## Setting up Site- and Platform-specific Settings | ||
| Site- and platform-specific settings are contained in | ||
| ```$LFRIC_CORE/infrastructure/build/site-specific/${SITE}-${PLATFORM}``` | ||
| The default settings are in ```.../site-specific/default``` (and at this | ||
| stage each other site-specific setup inherits the values set in the default, | ||
| and then adds or modifies settings). The Fab build system provides various | ||
| callbacks to the ```config.py``` file in the corresponding directory (details | ||
| are in the [Fab documentation](https://metoffice.github.io/fab/fab_base/config.html). | ||
|
|
||
| If there is no existing site-specific setup, it is recommended to copy an existing | ||
| configuration file (e.g. from ```nci_gadi/config.py```). This act as a template | ||
| to indicate where you can specify linker information, select a default compiler | ||
| suite etc. | ||
|
|
||
| The default setup contains compiler flags for Cray, GNU, Intel-classic (ifort), | ||
| Intel-LLVM (ifx), and NVIDIA. For modularity's sake (and to keep the file length | ||
| shorter), the default configuration will get the settings from the corresponding | ||
| ```setup_...py``` script. There is no need for a site to replicate this structure, | ||
| existing ```config.py``` scripts show how this can be done. | ||
|
|
||
|
|
||
| ## Building the Skeleton Apps | ||
|
|
||
| In order to build the skeleton apps, change into the directory | ||
| ```$LFRIC_CORE/applications/skeleton```, | ||
| and use the following command: | ||
|
|
||
| ``` | ||
| ./fab_skeleton.py --nprocs 4 --site nci --platform gadi --suite intel-classic | ||
| ``` | ||
| Select an appropriate number of processes to run in parallel, and your site and platform. | ||
| If you don't have a default compiler suite in your site-specific setup (or | ||
| want to use a non-default suite), use the ``--suite`` option. Once the process is finished, | ||
| you should have a binary in the directory | ||
| ```./fab-workspace/skeleton-full-debug-COMPILER``` (where ```COMPILER``` is the compiler | ||
| used, e.g. ```mpif90-gfortran```). | ||
|
|
||
| Using ```./fab_skeleton.py -h``` will show a help message with all supported command line | ||
| options (and their default value). If a default value is listed using an environment | ||
| variables (```(default: $SITE or 'default')```), the corresponding environment variable | ||
| is used if no command line option has been specified. | ||
|
|
||
| A different compilation profile can be specified using ```--profile``` option. Note | ||
| that the available compilation profiles can vary from site to site (see | ||
| [Fab documentation](https://metoffice.github.io/fab/fab_base/config.html) for details). | ||
|
|
||
| If Fab has issues finding a compiler, you can use the Fab debug option | ||
| ```--available-compilers```, which will list all compilers and linkers Fab has | ||
| identified as being available. |
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generic build components should be in |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| ############################################################################## | ||
| # (c) Crown copyright Met Office. All rights reserved. | ||
| # The file LICENCE, distributed with this code, contains details of the terms | ||
| # under which the code may be used. | ||
| ############################################################################## | ||
| # Author J. Henrichs, Bureau of Meteorology | ||
| # Author J. Lyu, Bureau of Meteorology | ||
|
|
||
| """ | ||
| This file defines the configurator script sequence for LFRic. | ||
| """ | ||
|
|
||
| import logging | ||
| from pathlib import Path | ||
| from typing import cast, Optional | ||
|
|
||
| from fab.api import BuildConfig, find_source_files, Category | ||
| from fab.tools.shell import Shell | ||
|
|
||
| from rose_picker_tool import RosePicker | ||
|
|
||
| logger = logging.getLogger('fab') | ||
|
|
||
|
|
||
| def configurator(config: BuildConfig, | ||
| lfric_core_source: Path, | ||
| rose_meta_conf: Path, | ||
| rose_picker: RosePicker, | ||
| include_paths: Optional[list[Path]] = None, | ||
| config_dir: Optional[Path] = None) -> None: | ||
| """ | ||
| This method implements the LFRic configurator tool. | ||
|
|
||
| :param config: the Fab build config instance | ||
| :param lfric_core_source: the path to the LFRic core directory | ||
| :param rose_meta_conf: the path to the rose-meta configuration file | ||
| :param rose_picker: the rose picker tool | ||
| :param include_paths: additional include paths (each path will be added, | ||
| as well as the path with /'rose-meta') | ||
| :param config_dir: the directory for the generated configuration files | ||
| """ | ||
|
|
||
| tools = lfric_core_source / 'infrastructure' / 'build' / 'tools' | ||
| config_dir = config_dir or config.build_output / 'configuration' | ||
| config_dir.mkdir(parents=True, exist_ok=True) | ||
|
|
||
| # rose picker | ||
| # ----------- | ||
| # creates rose-meta.json and config_namelists.txt in | ||
| # gungho/build | ||
| logger.info('rose_picker') | ||
|
|
||
| include_dirs = [lfric_core_source, lfric_core_source / 'rose-meta'] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Treating the metadata is one big bucket is undesirable. Consider how knowledge of which components are in use can be used to expose the appropriate metadata. |
||
| if include_paths: | ||
| for path in include_paths: | ||
| include_dirs.extend([path, path / 'rose-meta']) | ||
|
|
||
| parameters = [rose_meta_conf, '-directory', config_dir] | ||
| for incl_dir in include_dirs: | ||
| parameters.extend(['-include_dirs', incl_dir]) | ||
|
|
||
| rose_picker.execute(parameters=parameters) | ||
| rose_meta = config_dir / 'rose-meta.json' | ||
|
|
||
| shell = config.tool_box.get_tool(Category.SHELL) | ||
| shell = cast(Shell, shell) | ||
|
|
||
| # build_config_loaders | ||
| # -------------------- | ||
| # builds a bunch of f90s from the json | ||
| logger.info('GenerateNamelist') | ||
| shell.exec(f"{tools / 'GenerateNamelist'} -verbose {rose_meta} " | ||
| f"-directory {config_dir}") | ||
|
|
||
| # create configuration_mod.f90 in source root | ||
| # ------------------------------------------- | ||
| logger.info('GenerateLoader') | ||
| with open(config_dir / 'config_namelists.txt', encoding="utf8") as f_in: | ||
| names = [name.strip() for name in f_in.readlines()] | ||
|
|
||
| configuration_mod_fpath = config_dir / 'configuration_mod.f90' | ||
| shell.exec(f"{tools / 'GenerateLoader'} {configuration_mod_fpath} " | ||
| f"{' '.join(names)}") | ||
|
|
||
| # create feign_config_mod.f90 in source root | ||
| # ------------------------------------------ | ||
| logger.info('GenerateFeigns') | ||
| feign_config_mod_fpath = config_dir / 'feign_config_mod.f90' | ||
| shell.exec(f"{tools / 'GenerateFeigns'} {rose_meta} " | ||
| f"-output {feign_config_mod_fpath}") | ||
|
|
||
| find_source_files(config, source_root=config_dir) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Part of the user experience we want to have is that building is always achieved through the same procedure. Specifically, changing into a project directory and issuing a command. The same command. So please rename all build scripts to
build. Note that we do not add the.pyextension to executables.