Skip to content

Commit

Permalink
Merge branch '3_better_compiler_support' into add_standard_artefacts
Browse files Browse the repository at this point in the history
  • Loading branch information
hiker committed Jun 24, 2024
2 parents 52d5751 + 03bed8e commit c21d34f
Show file tree
Hide file tree
Showing 64 changed files with 943 additions and 842 deletions.
81 changes: 44 additions & 37 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,53 @@ on: [push, pull_request]
jobs:
build:

runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
strategy:
max-parallel: 4
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10']

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Setup Compiler
run: |
sudo apt-get -y install gcc gfortran
- name: Setup LibClang
run: |
sudo apt-get -y install libclang-dev python-clang
SP=~/.local/lib/python${{ matrix.python-version }}/site-packages
mkdir -p $SP
cp -vr /usr/lib/python3/dist-packages/clang $SP/
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
- name: Type check with mypy
run: |
pip install -e .[dev]
pip install pytest
python -m mypy source tests
- name: Code style check with flake8
run: |
pip install -e .[dev]
flake8 . --count --show-source --statistics
- name: Unit tests with Pytest
run: |
pip install .[tests]
python -m pytest --cov=fab tests/unit_tests
- name: System tests with Pytest
run: |
pip install .[tests]
python -m pytest --cov=fab tests/system_tests
# Should this step use a cache?
#
- name: Setup Compiler
run: |
sudo apt-get -y install llvm clang libclang-dev gcc gfortran
- uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip

# The clang binding version has to match the version in the Ubuntu being used.
- name: Install Python libraries
run: |
python -m pip install --upgrade pip
pip install -e .
pip install clang==14.0
- name: Type check with mypy
run: |
pip install -e .[dev]
pip install pytest
python -m mypy source tests
- name: Code style check with flake8
run: |
pip install -e .[dev]
flake8 . --count --show-source --statistics
- name: Unit tests with Pytest
run: |
pip install .[tests]
python -m pytest --cov=fab tests/unit_tests
- name: System tests with Pytest
run: |
pip install .[tests]
python -m pytest --cov=fab tests/system_tests
73 changes: 43 additions & 30 deletions .github/workflows/build_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,48 @@ on: workflow_dispatch
jobs:
build-docs:

runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- name: set git user
run: |
git config --global user.email "[email protected]"
git config --global user.name "SciFab Developers"
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: install fab
run: pip install .[docs]
- name: build docs
run: |
cd docs
rm -rf build
sphinx-apidoc --separate --module-first -d 5 -f -o source/apidoc ../source/fab
make html
- name: move built docs to docs root
run: |
mv docs/build/html/* docs/
- name: git add built docs
run: |
git add docs/*
- name: commit
run: |
git commit -m "docs build"
- name: push to gh_pages branch
run: |
echo "pushing from $GITHUB_REF_NAME to gh_pages"
git push --force origin $GITHUB_REF_NAME:gh_pages
- name: set git user
run: |
git config --global user.email "[email protected]"
git config --global user.name "SciFab Developers"
- name: Checkout Fab project files
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
cache: pip

- name: Install Python libraries
run: |
python -m pip install --upgrade pip
pip install -e .[docs]
- name: build docs
run: |
cd docs
rm -rf build
sphinx-apidoc --separate --module-first -d 5 -f -o source/apidoc ../source/fab
make html
- name: move built docs to docs root
run: |
mv docs/build/html/* docs/
- name: git add built docs
run: |
git add docs/*
- name: commit
run: |
git commit -m "docs build"
- name: push to gh_pages branch
run: |
echo "pushing from $GITHUB_REF_NAME to gh_pages"
git push --force origin $GITHUB_REF_NAME:gh_pages
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,29 @@

![](https://github.com/Metomi/fab/workflows/Build/badge.svg)

The "Fab" build system aims to provide a quick and easy build process tailored towards a
specific subset of scientific software developers. Quick should be in both use and
operation. Easy should mean the simple things are simple and the complicated things
possible.
The "Fab" project aims to provide the means to quickly and easily compile
software in a way tailored for scientific software development. It aims to be
quick both in terms of use and operation. Meanwhile ease should mean the
simple things are simple and the complicated things are possible.

The tool is not intended for general use outside its intended domain although you are,
of course, welcome to use it there. Just don't expect high priority to be given to
features which do not target scientific software development.
Fab is not intended to replace existing tools for compiling general
application software. It targets different problems to, for instance, CMake
derived build systems. This means that if your usage falls outside the focus
of development you shouldn't expect high priority on your feature requests.

## Licence

The software is made available under a 3-clause BSD licence.

## Installation

You may simply use `pip install sci-fab`.
The tool is easily installed using `pip install sci-fab`.

## Usage

Although Fab is in its initial development phases right now and much of the
functionality is yet to be added, the command line interface to the tool is
in place and can be run using the command `fab`
Fab offers two modes of operation. In "zero configuration" mode it is used
directly as a tool by running `fab`. This examines the currently selected
directory and tries to build whatever it finds there.

In "framework" mode it offers a library of building-blocks which a developer
can use to create a build system customised to the needs of their software.
61 changes: 39 additions & 22 deletions docs/source/site-specific-config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ Site-Specific Configuration
A site might have compilers that Fab doesn't know about, or prefers
a different compiler from the Fab default. Fab abstracts the compilers
and other programs required during building as an instance of a
:class:`~fab.tools.tool.Tool` class. All tools that Fab knows about, are
:class:`~fab.tools.Tool` class. All tools that Fab knows about, are
available in a :class:`~fab.tools.tool_repository.ToolRepository`.
That will include tools that might not be available on the current system.

Each tool belongs to a certain category of
:class:`~fab.tool.categories.Categories`. A `ToolRepository` can store
:class:`~fab.tool.category.Category`. A `ToolRepository` can store
several instances of the same category.

At build time, the user has to create an instance of
Expand All @@ -22,23 +22,31 @@ be defined in the toolbox, the default from the `ToolRepository` will
be used. This is useful for many standard tools like `git`, `rsync`
etc that de-facto will never be changed.

.. note:: If you need to use for example different compilers for
different files, you would implement this as a `meta-compiler`:
implement a new class based on the existing
:class:`~fab.tools.compiler.Compiler` class,
which takes two (or more) compiler instances. Its
:func:`~fab.tools.compiler.Compiler.compile_file`
method can then decide (e.g. based on the path of the file to
compile, or a hard-coded set of criteria) which compiler to use.

Categories
Category
==========
All possible categories are defined in
:class:`~fab.tool.categories.Categories`. If additional categories
:class:`~fab.tool.category.Category`. If additional categories
should be required, they can be added.

Tool
====
Each tool must be derived from :class:`~fab.tools.tool.Tool`.
Each tool must be derived from :class:`~fab.tools.Tool`.
The base class provides a `run` method, which any tool can
use to execute a command in a shell. Typically, a tool will
provide one (or several) custom commands to be used by the steps.
For example, a compiler instance provides a
:func:`~fab.tools.compiler.Compiler.compile_file` method.
This makes sure that no tool-specific command line options need
to be used in any Fab step, which will allow to replace any tool
to be used in any Fab step, which will allow the user to replace any tool
with a different one.

New tools can easily be created, look at
Expand All @@ -47,7 +55,7 @@ New tools can easily be created, look at
created by providing a different set of parameters in the
constructor.

This also allows to easily define compiler wrapper. For example,
This also allows compiler wrappers to be easily defined. For example,
if you want to use `mpif90` as compiler, which is a MPI-specific
wrapper for `ifort`, you can create this class as follows:

Expand All @@ -63,6 +71,9 @@ wrapper for `ifort`, you can create this class as follows:
super().__init__(name="mpif90-intel",
exec_name="mpif90")
.. note:: In `ticket 312 <https://github.com/metomi/fab/issues/312>`_ a better
implementation of compiler wrapper will be implemented.

Tool Repository
===============
The :class:`~fab.tools.tool_repository.ToolRepository` implements
Expand All @@ -80,32 +91,35 @@ startup section can add more tools to the repository:
tr = ToolRepository()
tr.add_tool(MpiF90) # the tool repository will create the instance
Compiler and linker objects define a vendor, and the `ToolRepository`
Compiler and linker objects define a compiler suite, and the `ToolRepository`
provides
:func:`~fab.tools.tool_repository.ToolRepository.set_default_vendor`
:func:`~fab.tools.tool_repository.ToolRepository.set_default_compiler_suite`
which allows you to change the defaults for compiler and linker with
a single call. This will allow you to easily switch from one compiler
to another.
to another. If required, you can still change any individual compiler
after setting a default compiler suite, e.g. you can define `intel-classic`
as default suite, but set the C-compiler to be `gcc`.


Tool Box
========
The class :class:`~fab.tools.tool_box.ToolBox` is used to provide
the tools to be use to the build environment, i.e. the
BuildConfig object:
the tools to be used by the build environment, i.e. the
`BuildConfig` object:

.. code-block::
:linenos:
:caption: ToolBox
from fab.tools import Categories, ToolBox, ToolRepository
from fab.tools import Category, ToolBox, ToolRepository
tr = ToolRepository()
tr.set_default_vendor("intel")
tr.set_default_compiler_suite("intel-classic")
tool_box = ToolBox()
ifort = tr.get_tool(Categories.FORTRAN_COMPILER, "ifort")
ifort = tr.get_tool(Category.FORTRAN_COMPILER, "ifort")
tool_box.add_tool(ifort)
c_comp = tr.get_default(Categories.C_COMPILER)
tool_box.add_tool(c_comp)
c_compiler = tr.get_default(Category.C_COMPILER)
tool_box.add_tool(c_compiler)
config = BuildConfig(tool_box=tool_box,
project_label=f'lfric_atm-{ifort.name}', ...)
Expand All @@ -115,21 +129,24 @@ it allows a site to replace a compiler in the tool repository (e.g.
if a site wants to use an older gfortran version, say one which is called
`gfortran-11`). They can then remove the standard gfortran in the tool
repository and replace it with a new gfortran compiler that will call
`gfortran-11` instead of `gfortran`.
`gfortran-11` instead of `gfortran`. But a site can also decide to
not support a generic `gfortran` call, instead adding different
gfortran compiler with a version number in the name.

If a tool category is not defined in the `ToolBox`, then
the default tool from the `ToolRepository` will be used. Therefore,
in the example above adding `ifort` is not strictly necessary (since
it will be the default after setting the default vendor to `intel`),
and `c_comp` is the default as well. This feature is especially useful
for the many default tools that Fab requires (git, rsync, ar, ...).
it will be the default after setting the default compiler suite to
`intel-classic`), and `c_compiler` is the default as well. This feature
is especially useful for the many default tools that Fab requires (git,
rsync, ar, ...).

.. code-block::
:linenos:
:caption: ToolBox
tool_box = ToolBox()
default_c_compiler = tool_box.get_tool(Categories.C_COMPILER)
default_c_compiler = tool_box.get_tool(Category.C_COMPILER)
TODO
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "sci-fab"
description = "Build system for scientific software"
authors = [
{name = "SciFab Developers", email = 'metomi@metoffice.gov.uk'}
{name = "Core Capabilities Development Team", email = 'CoreCapabilityDevelopmentTeam@metoffice.gov.uk'}
]
license = {file = 'LICENSE.txt'}
dynamic = ['version', 'readme']
Expand All @@ -19,7 +19,7 @@ classifiers = [
]

[project.optional-dependencies]
c-language = ['python-clang']
c-language = ['clang']
plots = ['matplotlib']
tests = ['pytest', 'pytest-cov', 'pytest-mock']
checks = ['flake8>=5.0.4', 'mypy']
Expand Down
Loading

0 comments on commit c21d34f

Please sign in to comment.