Formatters and Linters
Section author: Simeon Ehrig
Pre-commit
This project is set up for use with pre-commit. Using it will make your code conform with most of our (easily automatable) code style guidelines automatically. Pre-commit is a tool that manages git hooks conveniently for you. In very short (for anything further see pre-commit), after running the following in your working clone of alpaka
# if not yet done, install the pre-commit executable following https://pre-commit.com
cd /path/to/alpaka-working-clone
pre-commit install
git will run a number of checks prior to every commit and push and will refuse to perform the
pertinent action if they fail. Most of them (like e.g. the formatter) will have automatically altered your working tree
with the necessary changes such that
git add -u
will make the next commit pass. Although discouraged, in urgent cases it might be needed to be able to commit even if the checks fail. For such cases, you can either use
git commit --no-verify [...]
to completely skip all checks or use the more fine-grained control described here.
You can use
pre-commit run --all-files
to run all the hooks on all files.
Formatting
This section lists all formatters used in the alpaka project. Normally, you should use pre-commit to format your source code. If you want to format your code without pre-commit, e.g., automatically in your IDE, you will find all the necessary information in the following sections.
To get exactly the same formatted code as expected in CI, you must use the same formatting version locally as in CI. The specific formatting versions can be found in the .pre-commit-config.yaml file, see Formatter versions.
C++: Clang-Format
For C++ code, we use clang-format to format the code. Our style guide for C++ code is defined in the .clang-format file, which is provided in the top-level directory of alpaka.
CMake: Gersemi
The CMake code is formatted with gersemi.
Formatter versions
minimum_pre_commit_version: 3.2.0 # necessitated by Lucas-C's hooks
default_install_hook_types: [pre-commit, pre-push]
exclude: "thirdParty"
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v20.1.8
hooks:
- id: clang-format
files: \.(cpp|hpp)
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: no-commit-to-branch
args: [-b, develop]
- id: check-merge-conflict
- id: trailing-whitespace
exclude_types: [markdown, rst]
- id: end-of-file-fixer
exclude_types: [svg]
- id: check-yaml
- id: mixed-line-ending
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.5.5
hooks:
- id: forbid-tabs
types_or: [file]
exclude_types: [rst]
- id: remove-tabs
types_or: [file]
exclude_types: [rst]
- id: forbid-crlf
- id: remove-crlf
- repo: https://github.com/BlankSpruce/gersemi
rev: 0.22.1
hooks:
- id: gersemi
args: [-c, --diff]
- id: gersemi
args: [-i]
- repo: https://github.com/scop/pre-commit-shfmt
rev: v3.13.1-1
hooks:
- id: shfmt
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.11.0.1
hooks:
- id: shellcheck
# required that shellcheck can follow sourced scripts
args: [-x]
- repo: local
hooks:
- id: ascii-check
name: ASCII check
entry: python3 script/git_pre_commit/check_for_non_ascii.py
language: system
files: \.(c|cc|cpp|cxx|cu|h|hh|hpp|hxx|cuh)$
- repo: local
hooks:
- id: pragma-once
name: "Check #pragma once"
entry: script/git_pre_commit/check_pragma_once.sh
language: system
files: \.hpp$
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.21
hooks:
- id: ruff
types_or: [ python, pyi, jupyter ]
# The ignores in here are chosen to conform with the currently
# existing code and not motivated any other way.
args: [ --fix]
- id: ruff-format
types_or: [ python, pyi, jupyter ]
args: ["--line-length", "120"]
- repo: local
hooks:
- id: pylint
name: pylint
entry: pylint
language: python
types: [python]
additional_dependencies: [pylint]
require_serial: true
args:
[
"-rn", # Only display messages
"-sn", # Don't display the score
]
# source: https://github.com/pre-commit/pre-commit/issues/1470#issuecomment-634381955
exclude: |
(?x)(
^docs/
)
- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v2.3.0'
hooks:
- id: mypy
exclude: |
(?x)(
^docs/
)
Code Changes with Tools
In the alpaka project, we use many tools for developers. One type of these tools are formatting programs for C++ code, CMake code, and more. If a commit contains code changes created by a formatting program, the author of the commit should not be a real person. Instead of a real person, a non-existent tool author should be used. The reason for this approach is that we can use git blame to distinguish between what is a functional change in the code and what has only been formatted.
The tool author can be set with git commit --author="Tools <alpaka@hzdr.de>" when the commit is created.
If a commit contains code changes and reformatted code, it must be split into two commits. The first commit with the code changes (e.g., changing the formatter configuration) is created with the developer’s normal authorship. The second commit contains only the changes made by the tool and has tool as the authorship.
This PR shows how the changes are split into two commits: https://github.com/alpaka-group/alpaka3/pull/237