diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index b1cd4ee1fb..5fbdef5c4e 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -1,7 +1,6 @@ name: 'Benchmark' -on: - pull_request: +on: pull_request jobs: self: diff --git a/.github/workflows/count.yml b/.github/workflows/count.yml index 552e12b5e0..b0040b22ca 100644 --- a/.github/workflows/count.yml +++ b/.github/workflows/count.yml @@ -1,10 +1,6 @@ name: Check Line Counts -on: - push: - pull_request: - - workflow_dispatch: +on: [push, pull_request, workflow_dispatch] jobs: sz: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 0000000000..9d80fac80d --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,27 @@ +name: Coverage Check + +on: [push, pull_request, workflow_dispatch] + +jobs: + run: + name: Coverage Test on CodeCov + runs-on: "ubuntu-latest" + steps: + - name: Setup Ubuntu + run: | + sudo apt update -y + sudo apt install -y tar wget make cmake gcc g++ python3 python3-dev "openmpi-*" libopenmpi-dev + + - name: Checkouts + uses: actions/checkout@v4 + + - name: Build + run: /bin/bash mfc.sh build -j $(nproc) --gcov + + - name: Test + run: /bin/bash mfc.sh test -a -j $(nproc) + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ca22f9705f..acb1025b6e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,11 +1,6 @@ name: Lint -on: - push: - - pull_request: - - workflow_dispatch: +on: [push, pull_request, workflow_dispatch] jobs: docs: diff --git a/.github/workflows/pretty.yml b/.github/workflows/pretty.yml index 9181addf8a..b74ea79f3d 100644 --- a/.github/workflows/pretty.yml +++ b/.github/workflows/pretty.yml @@ -1,11 +1,6 @@ name: Pretty -on: - push: - - pull_request: - - workflow_dispatch: +on: [push, pull_request, workflow_dispatch] jobs: docs: diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 53f24e0024..582a91de95 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -1,7 +1,6 @@ name: Spell Check -on: - push: - workflow_dispatch: + +on: [push, workflow_dispatch] jobs: run: diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f2ef51fb9..bb36dd1862 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ project(MFC LANGUAGES C CXX Fortran) option(MFC_MPI "Build with MPI" ON) option(MFC_OpenACC "Build with OpenACC" OFF) +option(MFC_GCov "Build with GCov" OFF) option(MFC_PRE_PROCESS "Build pre_process" OFF) option(MFC_SIMULATION "Build simulation" OFF) option(MFC_POST_PROCESS "Build post_process" OFF) @@ -106,13 +107,34 @@ if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") $<$:-ffree-line-length-none> ) + if (MFC_GCov) + + # Warning present in gcc versions >= 12 that is treated as an error + # This flag doesn't exist in gcc versions < 12 + if (CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER 12) + add_compile_options( + -Wno-error=coverage-invalid-line-number + ) + endif() + + add_compile_options( + $<$:-fprofile-arcs> + $<$:-ftest-coverage> + ) + + add_link_options( + $<$:-lgcov> + $<$:--coverage> + ) + endif() + if (CMAKE_BUILD_TYPE STREQUAL "Debug") add_compile_options( -fcheck=all,no-array-temps -fbacktrace -fimplicit-none #-ffpe-trap=invalid,zero,denormal,overflow - ) + ) endif() if (CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER 10) diff --git a/README.md b/README.md index 20f9ff9ec3..735ff94bfa 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ + + +

Welcome to the home of MFC! diff --git a/docs/documentation/getting-started.md b/docs/documentation/getting-started.md index 271d9a086d..75b39270f0 100644 --- a/docs/documentation/getting-started.md +++ b/docs/documentation/getting-started.md @@ -177,6 +177,7 @@ MFC can be built with support for various (compile-time) features: | **MPI** | `--mpi` | `--no-mpi` | On | Lets MFC run on multiple processors (and nodes) simultaneously. | | **GPU** | `--gpu` | `--no-gpu` | Off | Enables GPU acceleration via OpenACC. | | **Debug** | `--debug` | `--no-debug` | Off | Requests the compiler build MFC in debug mode. | +| **GCov** | `--gcov` | `--no-gcov` | Off | Builds MFC with coverage flags on. | _⚠️ The `--gpu` option requires that your compiler supports OpenACC for Fortran for your target GPU architecture._ diff --git a/toolchain/main.py b/toolchain/main.py index af10904ac4..6465c3622a 100644 --- a/toolchain/main.py +++ b/toolchain/main.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -import signal, getpass, platform, itertools, dataclasses +import signal, getpass, platform, itertools from mfc import args, lock, build, bench, state, count from mfc.state import ARG @@ -21,11 +21,11 @@ def __print_greeting(): MFC_SIDEBAR_LINES = [ f"[bold]{host_line}[/bold]", '-' * len(host_line), - f"[bold]--jobs [magenta]{ARG('jobs')}[/magenta][/bold]" - ] + [ - f"[bold]--{'' if getattr(state.gCFG, field.name) else 'no-'}{field.name}[/bold]" for field in dataclasses.fields(state.gCFG) - ] + [ + '', + f"[bold]--jobs [magenta]{ARG('jobs')}[/magenta][/bold]", + f"[bold]{' '.join(state.gCFG.make_options())}[/bold]", targets_line if ARG("command") != "test" else "", + '', '-' * len(help_line), f"[yellow]{help_line}[/yellow]", ] diff --git a/toolchain/mfc/build.py b/toolchain/mfc/build.py index 700e1c90d2..9b6946a523 100644 --- a/toolchain/mfc/build.py +++ b/toolchain/mfc/build.py @@ -142,8 +142,9 @@ def configure(self, case: input.MFCInputFile): flags.append('--debug-find') if not self.isDependency: - flags.append(f"-DMFC_MPI={ 'ON' if ARG('mpi') else 'OFF'}") - flags.append(f"-DMFC_OpenACC={'ON' if ARG('gpu') else 'OFF'}") + flags.append(f"-DMFC_MPI={ 'ON' if ARG('mpi') else 'OFF'}") + flags.append(f"-DMFC_OpenACC={'ON' if ARG('gpu') else 'OFF'}") + flags.append(f"-DMFC_GCov={ 'ON' if ARG('gcov') else 'OFF'}") command = ["cmake"] + flags + ["-S", cmake_dirpath, "-B", build_dirpath] diff --git a/toolchain/mfc/common.py b/toolchain/mfc/common.py index 56cf9c5828..d91b68cc04 100644 --- a/toolchain/mfc/common.py +++ b/toolchain/mfc/common.py @@ -21,7 +21,7 @@ .:++=----------====+*= ==..:%..... .:-=++++===--==+=-+= +. := +#=::::::::=%=. -+: =+ *: -.*=-=*=.. :=+*+: -...--\ +.*=-=*=.. :=+*+: -...-- """ diff --git a/toolchain/mfc/lock.py b/toolchain/mfc/lock.py index 1513a8a43f..14139f9fff 100644 --- a/toolchain/mfc/lock.py +++ b/toolchain/mfc/lock.py @@ -5,7 +5,7 @@ from .printer import cons -MFC_LOCK_CURRENT_VERSION: int = 3 +MFC_LOCK_CURRENT_VERSION: int = 4 @dataclasses.dataclass diff --git a/toolchain/mfc/state.py b/toolchain/mfc/state.py index 1b06ed4cb0..1b69f0ed33 100644 --- a/toolchain/mfc/state.py +++ b/toolchain/mfc/state.py @@ -6,6 +6,7 @@ class MFCConfig: mpi: bool = True gpu: bool = False debug: bool = False + gcov: bool = False @staticmethod def from_dict(d: dict): @@ -23,12 +24,12 @@ def items(self) -> typing.List[typing.Tuple[str, bool]]: def make_options(self) -> typing.List[str]: """ Returns a list of options that could be passed to mfc.sh again. - Example: --no-debug --mpi --no-gpu """ + Example: --no-debug --mpi --no-gpu --no-gcov""" return [ f"--{'no-' if not v else ''}{k}" for k, v in self.items() ] def make_slug(self) -> str: """ Sort the items by key, then join them with underscores. This uniquely - identifies the configuration. Example: no-debug_no-gpu_mpi """ + identifies the configuration. Example: no-debug_no-gpu_no_mpi_no-gcov """ return '_'.join([ f"{'no-' if not v else ''}{k}" for k, v in sorted(self.items(), key=lambda x: x[0]) ]) def __eq__(self, other) -> bool: @@ -40,7 +41,7 @@ def __eq__(self, other) -> bool: return True def __str__(self) -> str: - """ Returns a string like "mpi=No & gpu=No & debug=No" """ + """ Returns a string like "mpi=No & gpu=No & debug=No & gcov=No" """ return ' & '.join([ f"{k}={'Yes' if v else 'No'}" for k, v in self.items() ])