FAQs
What tools are available for generating the compile_commands.json
file?
There are several tools available to generate the compile_commands.json
file. Here's a list of common tools, along with their compatibility across the different operating systems:
Tool | Description | Linux | Windows |
---|---|---|---|
CMake | Built-in support to generate the compile_commands.json | ✔ | ✔* |
Bear | Works with Makefile-based projects, intercepts build commands. | ✔ | ✘ |
Scons | Built-in support to generate the compile_commands.json | ✔ | ✔ |
Clang Power Tools | Visual Studio extension with a simplified interface. | ✔ | ✔ |
Ninja | Requires a Ninja build system setup. | ✔ | ✔ |
meson | Build-system that generates compile_commands.json by default | ✔ | ✔ |
Bazel | Build-system that can generate the compile_commands.json | ✔ | ✔ |
CompDB | Works for various build systems. | ✔ | ✔ |
* Note: Cmake only works in Windows for Ninja generators (cmake -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
)
What information is store in the compile_commands.json
file?
Here are some examples of compile_commands.json
files.
Example of a compile_commands.json
generated with CMake:
[
{
"directory": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/build",
"command": "/usr/bin/gcc -I/home/user/Appentra/repos/performance-demos/MATMUL/serial/include -O3 -DNDEBUG -fopenmp -o CMakeFiles/matmul.dir/matrix.c.o -c /home/user/Appentra/repos/performance-demos/MATMUL/serial/matrix.c",
"file": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/matrix.c"
},
{
"directory": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/build",
"command": "/usr/bin/gcc -I/home/user/Appentra/repos/performance-demos/MATMUL/serial/include -O3 -DNDEBUG -fopenmp -o CMakeFiles/matmul.dir/clock.c.o -c /home/user/Appentra/repos/performance-demos/MATMUL/serial/clock.c",
"file": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/clock.c"
},
{
"directory": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/build",
"command": "/usr/bin/gcc -I/home/user/Appentra/repos/performance-demos/MATMUL/serial/include -O3 -DNDEBUG -fopenmp -o CMakeFiles/matmul.dir/main.c.o -c /home/user/Appentra/repos/performance-demos/MATMUL/serial/main.c",
"file": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/main.c"
}
]
Example of a compile_commands.json
generated with Bear:
[
{
"arguments": [
"/usr/bin/cc",
"-c",
"-I",
"include",
"-fopenmp",
"-O3",
"-o",
"matmul",
"matrix.c"
],
"directory": "/home/user/Appentra/repos/performance-demos/MATMUL/serial",
"file": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/matrix.c",
"output": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/matmul"
},
{
"arguments": [
"/usr/bin/cc",
"-c",
"-I",
"include",
"-fopenmp",
"-O3",
"-o",
"matmul",
"clock.c"
],
"directory": "/home/user/Appentra/repos/performance-demos/MATMUL/serial",
"file": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/clock.c",
"output": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/matmul"
},
{
"arguments": [
"/usr/bin/cc",
"-c",
"-I",
"include",
"-fopenmp",
"-O3",
"-o",
"matmul",
"main.c"
],
"directory": "/home/user/Appentra/repos/performance-demos/MATMUL/serial",
"file": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/main.c",
"output": "/home/user/Appentra/repos/performance-demos/MATMUL/serial/matmul"
}
]
The main difference between the two examples is that bear uses the "arguments" terminology whereas CMake uses "command". The clang community prefers the use of Bear because of this, as shell (un)escaping is a possible source of errors. Clang 20.0.0 documentation
How to extend Codee to support a new LLVM based compiler
Bear currently supports, out of the box, GCC and Clang compilers for C/C++, and gfortran and Intel Fortran compilers for Fortran language.
However, Bear provides a way to add basic support to other compilers through the
--config
option specifying a configuration file which will contain the
path to the specific compiler binary.
For example, to add Flang, you can use this config file bear.config
:
{
"compilation":
{
"compilers_to_recognize": [
{
"executable": "/path/to/bin/flang",
"flags_to_add": [],
"flags_to_remove": []
}],
"compilers_to_exclude": []
},
"output":
{
"content":
{
"include_only_existing_source": true,
"paths_to_include": [],
"paths_to_exclude": [],
"duplicate_filter_fields": "file_output"
},
"format":
{
"command_as_array": true,
"drop_output_field": false
}
}
}
Then execute bear as usual adding --config
argument:
bear --config bear.config -- make
In case the resulting compile_commands.json
includes some entries with
unexpected commands we are not interested in, we can edit the file and
remove those entries.
For example, in the case of the AMD Optimizing C/C++ and Fortran Compilers
(AOCC), which uses an extended version of Clang and Flang, when using Bear to
create the compile_commands.json
, it generates unexpected command entries with
internal AOCC tools that cause conflicts with Codee and should be excluded from
the file.
To fix it, you can remove those entries automatically using this jq
(download) snippet:
jq '[.[] |
(.file | test("\\.f(90|95|03|08|\\d*)?$"; "i")) as $is_fortran |
(.arguments[0] | test("(^|/)(clang(\\+\\+)?(-[0-9\\.]+)?)$")) as $is_clang |
(.arguments | any(. == "-cc1")) as $has_cc1 |
select(
( $is_fortran | not ) or
( $is_clang | not ) or
( $is_clang and ( $has_cc1 | not ) )
)
]' compile_commands.json > fixed_compile_commands.json
mv fixed_compile_commands.json compile_commands.json
How to apply Codee filters?
In some cases, users may want to apply filters to the Codee invocation to analyze certain files instead of the entire project. To do this, refer to the following example;
codee screening file1.F90 file2.F90 --compile-commands compile_commands.json
With the command above, the screening output will only report information related to file1.F90
and file2.F90
.
Additional filters can be applied, allowing users to target specific loops or functions, limiting the resulting checkers to those that reference the specified sections. For example, to see the checkers that reference function1
in file1.F90
, use the following command:
codee checks file1.F90:function1 --compile-commands compile_commands.json
To apply a filter for a specific loop, specify the line where the loop begins. For instance, if the loop starts at line 30, use this command:
codee checks file1.F90:30 --compile-commands compile_commands.json
How to analyze only the files that have changed?
As a developer, it might be interesting to analyze only the files with changes in a Git repository. The following Bash script demonstrates how to use Codee to analyze only the subset of source files with unstaged changes:
#!/bin/bash
# List all unstaged source files with changes
changed_files=$(git diff --name-only --diff-filter=M | grep -E '\.(c|cpp|F90|f90)$')
# Check if there are any changed files
if [ -z "$changed_files" ]; then
echo "No unstaged changes found in source files."
exit 0
fi
# Run Codee with the list of changed files
codee screening $changed_files --compile-commands compile_commands.json
-
git diff --name-only --diff-filter=M
retrieves the list of modified files with unstaged changes. -
grep -E '\.(c|cpp|F90|f90)$'
filters this list, selecting only source files with specific extensions. -
Finally, the scripts runs
codee screening
on the filtered list of files, allowing Codee to only analyze those files with unstaged modifications.
* Note: Update the file extensions in the grep command based on your source file types (e.g., .f
, .f90
, .F90
). Also, make sure to specify the correct path to your
compile_commands.json
file if it is located elsewhere in your project. You can also modify the codee command to select another mode, for example, codee checks
.
This script is easily customizable and helps streamline the analysis process, ensuring that Codee is only targeting the files you're actively working on.
What type of licensing mechanism does Codee use?
Codee uses a license file-based system which is installed locally. The license file is specifically generated for the customer and must be installed on the machine where the software will be used.
The easiest way to setup the license file (what we most recommend) is to store the license file in the root directory of the Codee package with the name codee.lic
.
Alternatively, Codee can reach the license file through the CODEE_LICENSE_FILE=<full_path>
environment variable. This allows the user to place the license file in any
desired directory with any filename.