Skip to main content

Basic Workflow

Goal

Walk you through the suggested basic workflow for using Codee, demonstrated with a Fortran open source project.

Getting ready

For this demonstration, we will use the Fortran implementation of the Himeno benchmark, a Poisson equation solver. Start by cloning the repository:

git clone https://github.com/codee-com/codee-demos.git

Walkthrough of the workflow

Codee has multiple reports that can be useful but in this basic workflow we will focus on the Codee checkers.

0. Compiler Invocation

Firstly, navigate to the source code directory:

cd codee-demos/Fortran/Himeno

Before using Codee, ensure you have a working compiler invocation for the code to analyze. Himeno contains a single source file which can be compiled as:

gfortran -c himeno.f90

To generate any Codee report, simply add the compiler invocation to the right of the codee invocation after a -- separator.

1. Checks Report

To apply the recommendations from the Open Catalog, the checks report identifies the precise locations in the source code where the improvement opportunities have been found. The default checks report pinpoints the file, line, and column for each opportunity:

Codee command
codee checks -- gfortran -c himeno.f90
Codee output
CHECKS REPORT


himeno.f90 [PWR063] (level: L1): Avoid using legacy Fortran constructs
himeno.f90:67:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:136:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:164:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:223:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:255:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:275:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:136:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:164:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:223:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:255:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:275:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:325:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:136:1 [PWR001] (level: L3): Declare global variables as function parameters
himeno.f90:164:1 [PWR001] (level: L3): Declare global variables as function parameters
himeno.f90:223:1 [PWR001] (level: L3): Declare global variables as function parameters
himeno.f90:255:1 [PWR001] (level: L3): Declare global variables as function parameters
himeno.f90:275:1 [PWR001] (level: L3): Declare global variables as function parameters

SUGGESTIONS

Use --verbose to get more details, e.g:
codee checks --verbose -- gfortran -c himeno.f90

Use --check-id to focus on specific subsets of checkers, e.g.:
codee checks --check-id PWR063 -- gfortran -c himeno.f90

1 file, 7 functions, 5 loops, 214 LOCs successfully analyzed (18 checkers) and 0 non-analyzed files in 224 ms

We can also run the detailed output of the checks report (option --verbose) to obtain more information about each suggestion. This detailed output includes links to the Open Catalog, along with the precise location in the source code.

As an example, let's focus on the checker PWR069, related to module imports suggesting the use of the only keyword when importing from a module:

Codee command
codee checks --verbose --check-id PWR069 -- gfortran -c himeno.f90
Codee output
CHECKS REPORT

himeno.f90:67:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
The following use statement could import 'mimax', 'mjmax', 'mkmax', 'imax', 'jmax' and 'kmax' only:
68: use others
Suggestion: Enhance code clarity by leveraging the only keyword in use statements, clearly specifying which parts of a module are needed.
Documentation: https://github.com/codee-com/open-catalog/tree/main/Checks/PWR069
AutoFix:
codee rewrite --modernization uses --in-place himeno.f90:HimenoBMTxp_F90 -- gfortran -c himeno.f90

himeno.f90:136:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
The following use statement could import 'imax', 'mimax', 'jmax', 'mjmax', 'kmax' and 'mkmax' only:
138: use others
Suggestion: Enhance code clarity by leveraging the only keyword in use statements, clearly specifying which parts of a module are needed.
Documentation: https://github.com/codee-com/open-catalog/tree/main/Checks/PWR069
AutoFix:
codee rewrite --modernization uses --in-place himeno.f90:readparam -- gfortran -c himeno.f90

himeno.f90:164:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
The following use statement could import 'mimax', 'mjmax' and 'mkmax' only:
166: use others
Suggestion: Enhance code clarity by leveraging the only keyword in use statements, clearly specifying which parts of a module are needed.
Documentation: https://github.com/codee-com/open-catalog/tree/main/Checks/PWR069
AutoFix:
codee rewrite --modernization uses --in-place himeno.f90:grid_set -- gfortran -c himeno.f90

himeno.f90:223:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
The following use statement could import 'p' only:
225: use pres
The following use statement could import 'a', 'b' and 'c' only:
226: use mtrx
The following use statement could import 'bnd' only:
227: use bound
The following use statement could import 'wrk1' and 'wrk2' only:
228: use work
The following use statement could import 'imax', 'jmax' and 'kmax' only:
229: use others
Suggestion: Enhance code clarity by leveraging the only keyword in use statements, clearly specifying which parts of a module are needed.
Documentation: https://github.com/codee-com/open-catalog/tree/main/Checks/PWR069
AutoFix:
codee rewrite --modernization uses --in-place himeno.f90:initmt -- gfortran -c himeno.f90

himeno.f90:255:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
The following use statement could import 'p' only:
257: use pres
The following use statement could import 'a', 'b' and 'c' only:
258: use mtrx
The following use statement could import 'bnd' only:
259: use bound
The following use statement could import 'wrk1' and 'wrk2' only:
260: use work
The following use statement could import 'mimax', 'mjmax' and 'mkmax' only:
261: use others
Suggestion: Enhance code clarity by leveraging the only keyword in use statements, clearly specifying which parts of a module are needed.
Documentation: https://github.com/codee-com/open-catalog/tree/main/Checks/PWR069
AutoFix:
codee rewrite --modernization uses --in-place himeno.f90:initmem -- gfortran -c himeno.f90

himeno.f90:275:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
The following use statement could import 'p' only:
277: use pres
The following use statement could import 'a', 'b' and 'c' only:
278: use mtrx
The following use statement could import 'bnd' only:
279: use bound
The following use statement could import 'wrk1' and 'wrk2' only:
280: use work
The following use statement could import 'kmax', 'jmax', 'imax' and 'omega' only:
281: use others
Suggestion: Enhance code clarity by leveraging the only keyword in use statements, clearly specifying which parts of a module are needed.
Documentation: https://github.com/codee-com/open-catalog/tree/main/Checks/PWR069
AutoFix:
codee rewrite --modernization uses --in-place himeno.f90:jacobi -- gfortran -c himeno.f90

SUGGESTIONS

1 file, 7 functions, 5 loops, 214 LOCs successfully analyzed (6 checkers) and 0 non-analyzed files in 212 ms

2. Autofix

Follow Codee's suggestions and choose one of the PWR069 occurrences and apply its autofix. As an example, we will focus on the recomendation reported for line 67.

We can copy the command from the suggestions section:

Codee command
codee rewrite --modernization uses --in-place himeno.f90:HimenoBMTxp_F90 -- gfortran -c himeno.f90
Codee output
Date: 2024-11-14 Codee version: 2024.4 License type: Full
Compiler invocation: gfortran -c himeno.f90

Results for file '/user/codee-demos/Fortran/Himeno/himeno.f90':
Successfully applied AutoFix to the procedure at 'himeno.f90:67:1' [using adjust use expressions]:
[INFO] Adjusted use expressions:
- himeno.f90:67:1

Successfully updated /user/codee-demos/Fortran/Himeno/himeno.f90

Let's run the checks report once again to verify that PWR069 is no longer triggered for line 67:

Codee command
codee checks -- gfortran himeno.f90
Codee output
CHECKS REPORT

himeno.f90 [RMK015] (level: L1): Tune compiler optimization flags to increase the speed of the code
himeno.f90:297:12 [PWR054] (level: L1): Consider applying vectorization to scalar reduction loop
himeno.f90 [PWR063] (level: L1): Avoid using legacy Fortran constructs
himeno.f90:138:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:166:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:225:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:257:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:277:1 [PWR069] (level: L2): Use the keyword only to explicitly state what to import from a module
himeno.f90:138:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:166:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:225:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:257:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:277:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:327:1 [PWR068] (level: L3): Encapsulate external procedures within modules to avoid the risks of calling implicit interfaces
himeno.f90:295:6 [PWR035] (level: L3): Avoid non-consecutive array access to improve performance
himeno.f90:296:9 [PWR035] (level: L3): Avoid non-consecutive array access to improve performance
himeno.f90:138:1 [PWR001] (level: L3): Declare global variables as function parameters
himeno.f90:166:1 [PWR001] (level: L3): Declare global variables as function parameters
himeno.f90:225:1 [PWR001] (level: L3): Declare global variables as function parameters
himeno.f90:257:1 [PWR001] (level: L3): Declare global variables as function parameters
himeno.f90:277:1 [PWR001] (level: L3): Declare global variables as function parameters

SUGGESTIONS

Use --verbose to get more details, e.g:
codee checks --verbose -- gfortran himeno.f90

Use --check-id to focus on specific subsets of checkers, e.g.:
codee checks --check-id RMK015 -- gfortran himeno.f90

1 file, 7 functions, 5 loops, 214 LOCs successfully analyzed (21 checkers) and 0 non-analyzed files in 267 ms

As can be seen above, the PWR069 is no longer triggered for line 67.

3. Compilation Database

Codee requires the compiler invocation for each file to analyze. Sometimes the compiler invocation can be a huge command and there can be also multi-file projects. The recommended approach for this is to use a compilation database to efficiently handle the compiler invocations for different source files.

The generation of the compilation database depends on the particular build system used:

  • CMake: Add -DCMAKE_EXPORT_COMPILE_COMMANDS=ON to your usual CMake invocation; for instance:

    cmake . -DCMAKE_Fortran_COMPILER=gfortran -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G "Ninja" -B build
  • Makefiles: Since they do not natively support the generation of compilation databases, we recommend using bear. This tool is available on Linux systems through common package managers.

    To generate the compilation database, prepend bear -- to your typical make invocation; for example:

    bear -- make

Himeno supports both CMake and make.

Any of the above commands will generate a compile_commands.json file containing the compiler invocation for each file in the project. Since Himeno is a single-file project, the compilation database will have a single entry:

build/compile_commands.json
[
{
"directory": "/home/user/codee-demos/Fortran/Himeno/build",
"command": "/usr/bin/gfortran -c /home/user/codee-demos/Fortran/Himeno/himeno.f90 -o CMakeFiles/himeno.dir/himeno.f90.o",
"file": "/home/user/codee-demos/Fortran/Himeno/himeno.f90"
}
]

Now you can use the JSON generated to substitute the compilation command in the Codee invocation. For example:

Codee command
codee checks -p build/compile_commands.json