Basic Workflow
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:
- Linux
- Windows
cd codee-demos/Fortran/Himeno
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 checks -- gfortran -c himeno.f90
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 checks --verbose --check-id PWR069 -- gfortran -c himeno.f90
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 rewrite --modernization uses --in-place himeno.f90:HimenoBMTxp_F90 -- gfortran -c himeno.f90
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 checks -- gfortran himeno.f90
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 typicalmake
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:
[
{
"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 checks -p build/compile_commands.json