This document will guide you through DiffKemp development. It contains information about:
- How to set up development environment
- How to build DiffKemp
- How to check code follows the coding style
- Where the tests are located and how to run them
- How to add support for new version of LLVM
- Links to tools for performing experiments
- Useful links to learn more
To learn about how to contribute your changes to the main repository, read contributing guide.
For developing DiffKemp, you can use:
- Nix Flake
- Your local environment (installing dependencies directly to your system)
We provide Nix flakes for building and testing DiffKemp.
First, it is necessary to install Nix and enable flakes:
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.confThen, building DiffKemp is as simple as running one of the following commands:
nix build # <- uses latest LLVM
nix build .#diffkemp-llvm14This will create a new folder result/ containing the pre-built DiffKemp which
can be then executed by:
result/bin/diffkemp ...Tip
Rather than building DiffKemp with Nix, it is better to use Nix development environment described below, because the DiffKemp build created by Nix has following drawbacks:
- Currently it is not possible to run
viewsubcommand (the result viewer). - You still need to have some dependencies installed on your system to be able
to use it (
clang,llvm, and dependencies specific to the project you want to analyse).
It is also possible to use Nix as a development environment:
nix develop # <- uses latest LLVM
nix develop .#diffkemp-llvm14This will enter a development shell with all DiffKemp dependencies pre-installed. You can then follow the standard build instructions to build and install DiffKemp. The only difference is that you do not need to install the Python dependencies because they are already preinstalled.
The generated executable is then located in BUILD_DIR/bin/diffkemp.
We also provide a special Nix environment for retrieving and preparing kernel
versions necessary for running regression tests
(nix develop .#test-kernel-buildenv).
You can also develop DiffKemp directly. For this you need to install the necessary dependencies to your system and then you may build DiffKemp.
The generated executable is then located in BUILD_DIR/bin/diffkemp.
To build DiffKemp, use the following commands:
cmake -S . -B build -GNinja -DBUILD_VIEWER=On
ninja -C build-DBUILD_VIEWER=On: This flag will install packages and build the result viewer. It will try to install the packages on everycmakerun, so you may want to use-DBUILD_VIEWER=Offinstead.
If you make changes to the SimpLL library, you will need to rebuild it by
running ninja -C <BUILD_DIR>. We are using CFFI
for accessing the library from the Python.
To be able to use DiffKemp, it is also necessary to install Python dependencies, you can install them:
- by running
pip install . && pip uninstall -y diffkempor - install them manually by using
pip install <DEPENDENCIES>(dependencies are specified inpackagesfield inpyproject.tomlfile).
Note
If you used different than the default build directory (build) and want to
use pip install . for installing python dependencies, then you need to
specify the build directory when running pip by using
SIMPLL_BUILD_DIR=<BUILD_DIR> pip install ..
We require that the code is according to a certain coding style, which can be checked with the following tools:
- For Python code:
flake8 diffkemp tests. - For C++ code: it is necessary to have
clang-formatinstalled and the coding style can be checked withtools/check-clang-format.sh -d(it can be also automatically fixed by runningtools/check-clang-format.sh -di). - For JavaScript code:
npm --prefix view run lint.
The project contains multiple tests:
By default, the DiffKemp generates its own test runner executable located in
BUILD_DIR/bin/run_pytest_tests.py.
In addition to the standard diffkemp package you also have to install the
development dependencies by running:
pip instal .[dev]In a case where you have installed both the diffkemp package and development
dependencies you can run the tests by:
pytest testsThere are 2 types of tests:
- Unit tests (located in
tests/unit_tests/) - Regression tests (located in
tests/regression/)
The tests require the sources of the following kernel versions to be stored and
configured in kernel/linux-{version} directories:
- 3.10 (upstream kernel)
- 4.11 (upstream kernel)
- 3.10.0-514.el7 (CentOS 7.3 kernel)
- 3.10.0-693.el7 (CentOS 7.4 kernel)
- 3.10.0-862.el7 (CentOS 7.5 kernel)
- 3.10.0-957.el7 (CentOS 7.6 kernel)
- 4.18.0-80.el8 (RHEL 8.0 kernel)
- 4.18.0-147.el8 (RHEL 8.1 kernel)
- 4.18.0-193.el8 (RHEL 8.2 kernel)
- 4.18.0-240.el8 (RHEL 8.3 kernel)
The required configuration of each kernel can be done by running:
make prepare
make modules_prepareThe rhel-kernel-get script can also be used to download and configure the aforementioned kernels.
Tip
Since CentOS 7 kernels require a rather old GCC 7, the most convenient way to download the kernels is to use the prepared Nix environment by running
nix develop .#test-kernel-buildenvand using rhel-kernel-get inside the environment to retrieve the above
kernels.
Tests are located in tests/unit_tests/simpll/ directory and they can be run
by:
ninja -C build testIn case the tests fail, enabling logger can simplify the debugging process.
The logger is enabled by setting the SIMPLL_VERBOSITY environment variable to
a number, where:
0: No logging1: Minimal logging2: Moderate logging3and more: Detailed logging (the most verbose)
For example, to enable moderate logging while running tests with ninja, use
the following command:
SIMPLL_VERBOSITY=2 ninja -C build testThe result viewer contains unit tests and integration tests located in
view/src/tests/ directory and they can be run by:
npm --prefix view test -- --watchAll
npm --prefix view run cypress:runDiffkemp is based on augmentation of the
FunctionComparator;
however, this class is not polymorphic in the upstream and because of that we
have to add it to the project manually. The steps required to do so are:
- Extract the
FunctionComparator.cppandFunctionComparator.hfrom the LLVM project monorepo, take the most recent release of your target major version (i.e., prefer 19.1.7 over 19.1.6). - Create a new subdirectory at path
diffkemp/simpll/llvm-lib/<MAJOR VERSION>, whereMAJOR VERSIONis the major version of the LLVM that you want to support. - Move all private methods of
FunctionComparatorto protected scope. - Make all methods of
FunctionComparatorandGlobalNumberStatevirtual. - Change the path to
FunctionComparatorheader in the source file of the version that you are adding (it has to be made local, instead of including the LLVM one).- #include "llvm/Transforms/Utils/FunctionComparator.h" + #include "FunctionComparator.h"
- Update CI (i.e., add the new version to the list here and change the most recent LLVM version here and in the code style check) and Nix (change the range of supported version here) files with your new version. You also have to update the docs.
- Make the project compilable and resolve any performance issues. However, you have to make sure that the source code of the whole project is working with all supported LLVM versions. This is usually achieved by introduction of preprocessor directives into the code, an example can found here.
We have some tools which can be handy when developing DiffKemp:
- Tool for building and subsequently comparing multiple versions of a provided C project
- Tool for checking semantic equality of several commits using DiffKemp
- Tool for running DiffKemp with EqBench dataset of equivalent and non-equivalent program pairs: You can use this tool if you make bigger changes to the SimpLL library to ensure that the evaluation results are not worse than before.