From 8aaff8d5fd03b0fa8979a4d5195986d1ee3e2b90 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 14 Aug 2026 00:05:29 +0200 Subject: [PATCH] Simple README.md and large docs/ --- README.md | 507 ++++--------------------------------------------- docs/README.md | 505 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 539 insertions(+), 473 deletions(-) create mode 100644 docs/README.md diff --git a/README.md b/README.md index ed350b7c..81205ba1 100644 --- a/README.md +++ b/README.md @@ -1,505 +1,66 @@ -Bazel Rules for CodeChecker -=========================== +# Bazel Rules for CodeChecker -Bazel rules for CodeChecker and other tools for Code Analysis, -including Clang-tidy, Clang analyzer, generating compilation database -(`compile_commands.json`) and others. +Bazel rules for [CodeChecker](https://github.com/Ericsson/codechecker) and other tools for Code Analysis, +like Clang-tidy, Clang analyzer, and compilation database (`compile_commands.json`) generation. -> If you would like to report an issue or suggest a change -> please read [CONTRIBUTING.md](CONTRIBUTING.md). -### CodeChecker +## Get Started -CodeChecker is a static analysis infrastructure that conveniently manages static analyzer engines such as the Clang Static Analyzer, Clang-tidy, GCC Static Analyzer, CppCheck and Infer. +> [!Tip] +> You may try this on zlib: +> `git clone https://github.com/madler/zlib.git` +> `cd zlib` -Read about CodeChecker: +### Prerequisites -* GitHub: https://github.com/Ericsson/codechecker -* Read the Docs: https://codechecker.readthedocs.io/ - -The main Bazel rule for CodeChecker is `codechecker_test()`. - -### Clang-tidy - -Clang-tidy is a fast static analyzer/linter for the C family of languages. -This repository provides Bazel rule `clang_tidy_test()` -to run clang-tidy natively (without CodeChecker). - -Find more information about LLVM clang-tidy: - -* LLVM: https://clang.llvm.org/extra/clang-tidy -* bazel_clang_tidy: https://github.com/erenon/bazel_clang_tidy - -### Clang Static Analyzer - -The Clang Static Analyzer (or `clang --analyze`) is among -the most sophisticated tools for C/C++ code analysis which implements -path-sensitive, inter-procedural analysis based on symbolic execution technique. -This repository provides the Bazel rule `clang_analyze_test()` which runs the -Clang Static Analyzer natively (without CodeChecker) - -Find more information about LLVM Clang Static Analyzer: - -* LLVM: https://clang.llvm.org/docs/ClangStaticAnalyzer.html - -### Generating a compilation database - -There is also a Bazel rule for generating a compilation database (compile_commands.json) via `compile_commands()`. The current implementation is Bazel native and doesn't use `CodeChecker log`. - -Prerequisites -------------- - -We need the following tools: - -- Git 2 or newer -- Bazel 7.7 +- Bazel 7 or 8 (not 9 yet) +- CodeChecker 6.27.3 - Clang and clang-tidy 21 - Python 3.11 or newer -- CodeChecker 6.27.3 - -If, by chance, Environment Modules (https://modules.sourceforge.net/) -are available in your system, you can just add the following modules: - - module add git - module add bazel/7 - module add clang/21 - module add python/3.11 - module add codechecker/6.27.3 - - -Getting Started ---------------- - -Install dependencies: - -RHEL 9: -```bash -dnf update -y && dnf install -y wget llvm-toolset clang-tools-extra git python3 python3-pip gcc g++ -``` - -Ubuntu: -```bash -sudo apt-get update --quiet && sudo apt-get install --no-install-recommends wget git python3 python3-pip python3-venv gcc g++ clang clang-tools clang-tidy -``` - -On some distributions, `clang`, `clang-tidy` and `clang-extdef-mapping` may be installed with a trailing version number (e.g. clang-extdef-mapping-18). In case your package didn't install a non-versioned symlink as well, you will need to manually change it: -```bash -update-alternatives --install /usr/bin/clang-extdef-mapping clang-extdef-mapping /usr/bin/clang-extdef-mapping-18 100 -update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-18 100 -update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 100 -``` - -Install CodeChecker: -> [!Note] -> Currently the pip installed CodeChecker works best with these rules, which is our recommendation (as opposed to using a custom-built CodeChecker). +Check that you have all tools and versions: ```bash -python3 -m venv ./codechecker_venv && \ -source ./codechecker_venv/bin/activate && \ -pip3 install codechecker +bazel version +CodeChecker version +python3 --version +clang --version +clang-tidy --version +clang-extdef-mapping --version +which diagtool ``` -Install Bazel: -We recommend bazel 8.5.0 -```bash -wget https://github.com/bazelbuild/bazel/releases/download/8.5.0/bazel-8.5.0-linux-x86_64 && \ -chmod +x bazel-8.5.0-linux-x86_64 && \ -sudo mv bazel-8.5.0-linux-x86_64 /usr/local/bin/bazel -``` -Or choose a suitable binary for your system from this list: https://github.com/bazelbuild/bazel/releases/tag/7.7.0 -Alternatively follow the official guide at: https://bazel.build/install - -> [!CAUTION] -> Don't use ccache! You should disable/remove/uninstall it, as the rules don't support it. - - -> [!WARNING] -> When debugging, or reporting a bug, take into consideration which sandbox mode did bazel ran in. Be careful as the default sandbox can change if you ran [Bazel inside Docker](https://bazel.build/versions/6.5.0/docs/sandboxing#:~:text=Both%20the%20linux,run%20%2D%2Dprivileged.). +### Add to `MODULE.bazel` file: -How to use ----------- - -To use these rules you should first add `rules_codechecker` as a -[Bazel module](https://bazel.build/external/module) in your `MODULE.bazel`: - -``` +```starlark +bazel_dep(name = "rules_codechecker") git_override( module_name = "rules_codechecker", remote = "https://github.com/Ericsson/rules_codechecker.git", - commit = "", + commit = "cb57742eeaec172de042258a6053d87aee51e808", ) -bazel_dep(name = "rules_codechecker") - ``` -## CodeChecker +### Add to `BUILD.bazel` (or `BUILD`) file: -### Standard CodeChecker invocation: `codechecker_test()` +```starlark +load("@rules_codechecker//:defs.bzl", "codechecker_test") -`codechecker_test()` invokes CodeChecker the "standard way", as you'd call -it normally from the command line. The rule first generates a compilation -database on all targets given to the rule. Then, [`CodeChecker analyze`](https://github.com/Ericsson/codechecker/blob/master/docs/analyzer/user_guide.md#analyze) -is run on all translation units found in those targets. - -> [!NOTE] -> Even though bazel is capable of incremental builds, if any files are -> rebuilt, this rule will reanalyze all translation units in all targets, -> even those that needed no rebuild. - -To use `codechecker_test()` include it to your BUILD file: - -```python -load( - "@rules_codechecker//:defs.bzl", - "codechecker_test", -) -``` - -Create a `codechecker_test()` target by passing other targets you'd like CodeChecker to analyze: - - -```python -codechecker_test( - name = "your_codechecker_rule_name", - targets = [ - "your_target", - ], -) -``` - -#### Per-file CodeChecker analysis: -> [!IMPORTANT] -> The option is still in prototype status and is subject to changes or removal without notice. See [#31](https://github.com/Ericsson/rules_codechecker/issues/31). -> You are free to experiment and report issues however! - -Instead of a single CodeChecker call, adding `per_file = True,` parameter to codechecker_test bazel rule invokes -[`CodeChecker analyze`](https://github.com/Ericsson/codechecker/blob/master/docs/analyzer/user_guide.md#analyze) -_for each_ translation unit in the targets to analyze. This method is intended to be -able to enable incremental analyses and dispatching analysis jobs to remote build -agents. - - -Create a `codechecker_test()` target and add the `per_file = True,` parameter: - -```python codechecker_test( - name = "your_codechecker_rule_name", - targets = [ - "your_target", - ], - per_file = True, + name = "codechecker", + targets = [":z"], ) ``` -Then invoke bazel: - +### Run: ```bash -bazel test //:your_codechecker_rule_name -# Or, as a part of the rest of the testsuite -bazel test ... -``` - -> [!WARNING] -> Filtering codechecker_tests with only `--test_tag_filters=-codechecker` is not enough. -> To skip the actual analysis `--build_tag_filters=-codechecker` must also be specified. - -You can find the analysis results in the `bazel-bin/` folder, on which you -can run [`CodeChecker store`](https://github.com/Ericsson/codechecker/blob/master/docs/web/user_guide.md#store) -or [`CodeChecker parse`](https://github.com/Ericsson/codechecker/blob/master/docs/analyzer/user_guide.md#parse). -The precise output path to the directory can vary, but you should look for `your_codechecker_rule_name/codechecker-files/data`. -In simpler cases, something like the following: - -```bash -CodeChecker parse bazel-bin/your_codechecker_rule_name/codechecker-files/data -CodeChecker store bazel-bin/your_codechecker_rule_name/codechecker-files/data -n "Run name" -``` - - - -#### Skipping files - -The `skip` argument accepts a list of patterns using the -[CodeChecker skip-file syntax](https://codechecker.readthedocs.io/en/latest/analyzer/user_guide/#skip-file). -Because CodeChecker runs inside the Bazel sandbox, skip patterns cannot use -absolute paths from the host system. Use workspace-relative patterns instead, -with a leading wildcard when the sandbox path prefix can vary: - -```python -codechecker_test( - name = "your_codechecker_rule_name", - skip = [ - "-*path/to/skipped/files/*", - ], - targets = [ - "your_target", - ], -) -``` - -The `skip` argument is supported by both the standard analysis and the -experimental per-file analysis enabled with `per_file = True`. - -### Multi-platform CodeChecker analysis: `codechecker_suite()` -_TODO: Describe this rule: see issue [#44](https://github.com/Ericsson/rules_codechecker/issues/44)._ - -### `codechecker_config()` -Using the Bazel rule `codechecker_config()` you can utilize a CodeChecker [configuration file](https://github.com/Ericsson/codechecker/blob/master/docs/config_file.md). -First, include the rule in your BUILD file: +## Documentation -```python -load( - "@rules_codechecker//:defs.bzl", - "codechecker_config" -) -``` - -Create a CodeChecker configuration file e.g. `config.json` (see example [test/config.json](test/config.json)) and parse it using `codechecker_config()`. - -```python -codechecker_config( - name = "your_codechecker_config", - config_file = ":config.json" -) -``` - -Alternatively, you can assemble a CodeChecker configuration without a config file using the rule: - -```python -codechecker_config( - name = "your_codechecker_config", - analyze = [ - "--enable=bugprone-dangling-handle", - "--enable=bugprone-fold-init-type", - "--enable=misc-non-copyable-objects", - "--report-hash=context-free-v2", - ] -) -``` - -You can now configure your `codechecker_suite()` and `codechecker_test()` targets using the above configuration: - -```python -codechecker_test( - name = "your_codechecker_rule_name", - config = "your_codechecker_config", - targets = [ - "your_target", - ], -) -``` - -## CodeChecker independent rules - -The following rules are _not_ using CodeChecker. - -### Clang-tidy: `clang_tidy_test()` - -The Bazel rule `clang_tidy_test()` runs clang-tidy natively without CodeChecker. -To use it, add the following to your BUILD file: - -```python -load( - "@rules_codechecker//:defs.bzl", - "clang_tidy_test", -) - -clang_tidy_test( - name = "your_rule_name", - targets = [ - "your_target", - ], -) -``` - -### Clang Static Analyzer: `clang_analyze_test()` - -The Bazel rule `clang_analyze_test()` runs The Clang Static Analyzer -natively without CodeChecker. -To use it, add the following to your BUILD file: - -```python -load( - "@rules_codechecker//:defs.bzl", - "clang_analyze_test", -) - -clang_analyze_test( - name = "your_rule_name", - targets = [ - "your_target", - ], -) -``` - -> [!Note] -> Currently `clang_analyze_test()` rule does not support CTU (Cross Translation Unit) analysis. - -### Generating a compilation database: `compile_commands()` - -As generating a compilation database for C/C++ is a known pain point for bazel, this repository defines the Bazel rule `compile_commands()` rule which can be used independently of CodeChecker. The implementation is based on https://github.com/grailbio/bazel-compilation-database with some fixes on some tricky edge cases. To use it, include the following in your BUILD file: - -```python -load( - "@rules_codechecker//:defs.bzl", - "compile_commands", -) -``` - -Then use `compile_commands()` rule passing build targets: +Full documentation: [docs/](docs/) -```python -compile_commands( - name = "your_compile_commands_rule_name", - targets = [ - "your_target", - ], -) -``` -You can find the generated `compile_commands.json` under `bazel-bin/`. - -## Experimental rules - -### Cross-translation unit analysis via the Clang Static Analyzer: `clang_ctu_test()` -> [!IMPORTANT] -> The rule is still in prototype status and is subject to changes or removal without notice. See [#32](https://github.com/Ericsson/rules_codechecker/issues/32). -> We are also actively pursuing better CTU support _using_ CodeChecker. - -The Bazel rule `clang_analyze_test()` runs The Clang Static Analyzer with [cross translation unit analysis](https://clang.llvm.org/docs/analyzer/user-docs/CrossTranslationUnit.html) analysis without CodeChecker. To use it, add the following to your BUILD file: - -```python -load( - "@rules_codechecker//src:clang_ctu.bzl", - "clang_ctu_test", -) - -clang_ctu_test( - name = "your_clang_ctu_rule_name", - targets = [ - "your_target", - ], -) -``` - -Examples --------- - -In [test/BUILD](test/BUILD) you can find examples for `codechecker_test()` -and for `compile_commands()` rules. - -For instance see targets `codechecker_pass` and `compile_commands_pass`. - -Run all test Bazel targets: - - bazel test ... - -After that you can find all artifacts in `bazel-bin` directory: - - # All codechecker_pass artifacts - ls bazel-bin/test/codechecker_pass/ - - # compile_commands.json for compile_commands_pass - cat bazel-bin/test/compile_commands_pass/compile_commands.json - -Toolchains ----------- - -The previous rules locate the CodeChecker, Clang and clang-tidy executables through a -Bazel [toolchain](https://bazel.build/extending/toolchains). Modeling the tools -as a toolchain means the analysis rule (`codechecker_test`) never hardcode binary paths: -Bazel resolves the correct tools at build time, and you can override them -per-project or per-platform without touching the rules themselves. - -### The default toolchain - -For most users no setup is required. `rules_codechecker` ships with a module -extension that provisions a default set of tools and a pre-registered -toolchain. - -> [!NOTE] -> The default tools resolve to the `CodeChecker`, `clang` and `clang-tidy` -> binaries available from PATH on your system (see the [Prerequisites](#prerequisites)). - -To enable it, add the following to your `MODULE.bazel`: - -```python -codechecker_extension = use_extension( - "@rules_codechecker//src:tools.bzl", - "module_register_default_codechecker_tools", -) -use_repo(codechecker_extension, "default_codechecker_tools") -register_toolchains("@rules_codechecker//src:codechecker_local_toolchain") -``` - -### Providing your own tools - -If you don't want the default system tools -- for example to pin a specific -CodeChecker version or point at a custom build —- you can define and register your own toolchain. - -First, you will have to create or obtain labels for codechecker, clang and clang-tidy. - -You may create such a label like this: -```python -filegroup( - name = "clang", - srcs = ["/usr/bin/clang"], - visibility = ["//visibility:public"], -) -``` - -Then define an implementation in a BUILD file with `codechecker_toolchain()`: - -```python -load( - "@rules_codechecker//:defs.bzl", - "codechecker_toolchain", -) - -codechecker_toolchain( - name = "codechecker_custom", - clang_tidy = "//example_target:clang-tidy", - clangsa = "//example_target:clang", - codechecker = "//example_target:CodeChecker", -) - -toolchain( - name = "codechecker_custom_toolchain", - toolchain = ":codechecker_custom", - toolchain_type = "@rules_codechecker//src:toolchain_type", - # Optionally constrain which execution platform this applies to: - # exec_compatible_with = ["@platforms//os:linux"], -) -``` -Finally register it in your `MODULE.bazel`: -```python -register_toolchains("//path/to:codechecker_custom_toolchain") -``` +## Contributing -[!NOTE] -> Toolchains you register yourself take precedence over the default one if registered earlier. +See [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..ed350b7c --- /dev/null +++ b/docs/README.md @@ -0,0 +1,505 @@ +Bazel Rules for CodeChecker +=========================== + +Bazel rules for CodeChecker and other tools for Code Analysis, +including Clang-tidy, Clang analyzer, generating compilation database +(`compile_commands.json`) and others. + +> If you would like to report an issue or suggest a change +> please read [CONTRIBUTING.md](CONTRIBUTING.md). + +### CodeChecker + +CodeChecker is a static analysis infrastructure that conveniently manages static analyzer engines such as the Clang Static Analyzer, Clang-tidy, GCC Static Analyzer, CppCheck and Infer. + +Read about CodeChecker: + +* GitHub: https://github.com/Ericsson/codechecker +* Read the Docs: https://codechecker.readthedocs.io/ + +The main Bazel rule for CodeChecker is `codechecker_test()`. + +### Clang-tidy + +Clang-tidy is a fast static analyzer/linter for the C family of languages. +This repository provides Bazel rule `clang_tidy_test()` +to run clang-tidy natively (without CodeChecker). + +Find more information about LLVM clang-tidy: + +* LLVM: https://clang.llvm.org/extra/clang-tidy +* bazel_clang_tidy: https://github.com/erenon/bazel_clang_tidy + +### Clang Static Analyzer + +The Clang Static Analyzer (or `clang --analyze`) is among +the most sophisticated tools for C/C++ code analysis which implements +path-sensitive, inter-procedural analysis based on symbolic execution technique. +This repository provides the Bazel rule `clang_analyze_test()` which runs the +Clang Static Analyzer natively (without CodeChecker) + +Find more information about LLVM Clang Static Analyzer: + +* LLVM: https://clang.llvm.org/docs/ClangStaticAnalyzer.html + +### Generating a compilation database + +There is also a Bazel rule for generating a compilation database (compile_commands.json) via `compile_commands()`. The current implementation is Bazel native and doesn't use `CodeChecker log`. + +Prerequisites +------------- + +We need the following tools: + +- Git 2 or newer +- Bazel 7.7 +- Clang and clang-tidy 21 +- Python 3.11 or newer +- CodeChecker 6.27.3 + +If, by chance, Environment Modules (https://modules.sourceforge.net/) +are available in your system, you can just add the following modules: + + module add git + module add bazel/7 + module add clang/21 + module add python/3.11 + module add codechecker/6.27.3 + + +Getting Started +--------------- + +Install dependencies: + +RHEL 9: +```bash +dnf update -y && dnf install -y wget llvm-toolset clang-tools-extra git python3 python3-pip gcc g++ +``` + +Ubuntu: +```bash +sudo apt-get update --quiet && sudo apt-get install --no-install-recommends wget git python3 python3-pip python3-venv gcc g++ clang clang-tools clang-tidy +``` + +On some distributions, `clang`, `clang-tidy` and `clang-extdef-mapping` may be installed with a trailing version number (e.g. clang-extdef-mapping-18). In case your package didn't install a non-versioned symlink as well, you will need to manually change it: +```bash +update-alternatives --install /usr/bin/clang-extdef-mapping clang-extdef-mapping /usr/bin/clang-extdef-mapping-18 100 +update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-18 100 +update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 100 +``` + +Install CodeChecker: +> [!Note] +> Currently the pip installed CodeChecker works best with these rules, which is our recommendation (as opposed to using a custom-built CodeChecker). + +```bash +python3 -m venv ./codechecker_venv && \ +source ./codechecker_venv/bin/activate && \ +pip3 install codechecker +``` + +Install Bazel: +We recommend bazel 8.5.0 +```bash +wget https://github.com/bazelbuild/bazel/releases/download/8.5.0/bazel-8.5.0-linux-x86_64 && \ +chmod +x bazel-8.5.0-linux-x86_64 && \ +sudo mv bazel-8.5.0-linux-x86_64 /usr/local/bin/bazel +``` +Or choose a suitable binary for your system from this list: https://github.com/bazelbuild/bazel/releases/tag/7.7.0 +Alternatively follow the official guide at: https://bazel.build/install + +> [!CAUTION] +> Don't use ccache! You should disable/remove/uninstall it, as the rules don't support it. + + +> [!WARNING] +> When debugging, or reporting a bug, take into consideration which sandbox mode did bazel ran in. Be careful as the default sandbox can change if you ran [Bazel inside Docker](https://bazel.build/versions/6.5.0/docs/sandboxing#:~:text=Both%20the%20linux,run%20%2D%2Dprivileged.). + +How to use +---------- + +To use these rules you should first add `rules_codechecker` as a +[Bazel module](https://bazel.build/external/module) in your `MODULE.bazel`: + +``` +git_override( + module_name = "rules_codechecker", + remote = "https://github.com/Ericsson/rules_codechecker.git", + commit = "", +) +bazel_dep(name = "rules_codechecker") + +``` + +## CodeChecker + +### Standard CodeChecker invocation: `codechecker_test()` + +`codechecker_test()` invokes CodeChecker the "standard way", as you'd call +it normally from the command line. The rule first generates a compilation +database on all targets given to the rule. Then, [`CodeChecker analyze`](https://github.com/Ericsson/codechecker/blob/master/docs/analyzer/user_guide.md#analyze) +is run on all translation units found in those targets. + +> [!NOTE] +> Even though bazel is capable of incremental builds, if any files are +> rebuilt, this rule will reanalyze all translation units in all targets, +> even those that needed no rebuild. + +To use `codechecker_test()` include it to your BUILD file: + +```python +load( + "@rules_codechecker//:defs.bzl", + "codechecker_test", +) +``` + +Create a `codechecker_test()` target by passing other targets you'd like CodeChecker to analyze: + + +```python +codechecker_test( + name = "your_codechecker_rule_name", + targets = [ + "your_target", + ], +) +``` + +#### Per-file CodeChecker analysis: +> [!IMPORTANT] +> The option is still in prototype status and is subject to changes or removal without notice. See [#31](https://github.com/Ericsson/rules_codechecker/issues/31). +> You are free to experiment and report issues however! + +Instead of a single CodeChecker call, adding `per_file = True,` parameter to codechecker_test bazel rule invokes +[`CodeChecker analyze`](https://github.com/Ericsson/codechecker/blob/master/docs/analyzer/user_guide.md#analyze) +_for each_ translation unit in the targets to analyze. This method is intended to be +able to enable incremental analyses and dispatching analysis jobs to remote build +agents. + + +Create a `codechecker_test()` target and add the `per_file = True,` parameter: + +```python +codechecker_test( + name = "your_codechecker_rule_name", + targets = [ + "your_target", + ], + per_file = True, +) +``` + +Then invoke bazel: + +```bash +bazel test //:your_codechecker_rule_name +# Or, as a part of the rest of the testsuite +bazel test ... +``` + +> [!WARNING] +> Filtering codechecker_tests with only `--test_tag_filters=-codechecker` is not enough. +> To skip the actual analysis `--build_tag_filters=-codechecker` must also be specified. + +You can find the analysis results in the `bazel-bin/` folder, on which you +can run [`CodeChecker store`](https://github.com/Ericsson/codechecker/blob/master/docs/web/user_guide.md#store) +or [`CodeChecker parse`](https://github.com/Ericsson/codechecker/blob/master/docs/analyzer/user_guide.md#parse). +The precise output path to the directory can vary, but you should look for `your_codechecker_rule_name/codechecker-files/data`. +In simpler cases, something like the following: + +```bash +CodeChecker parse bazel-bin/your_codechecker_rule_name/codechecker-files/data +CodeChecker store bazel-bin/your_codechecker_rule_name/codechecker-files/data -n "Run name" +``` + + + +#### Skipping files + +The `skip` argument accepts a list of patterns using the +[CodeChecker skip-file syntax](https://codechecker.readthedocs.io/en/latest/analyzer/user_guide/#skip-file). +Because CodeChecker runs inside the Bazel sandbox, skip patterns cannot use +absolute paths from the host system. Use workspace-relative patterns instead, +with a leading wildcard when the sandbox path prefix can vary: + +```python +codechecker_test( + name = "your_codechecker_rule_name", + skip = [ + "-*path/to/skipped/files/*", + ], + targets = [ + "your_target", + ], +) +``` + +The `skip` argument is supported by both the standard analysis and the +experimental per-file analysis enabled with `per_file = True`. + +### Multi-platform CodeChecker analysis: `codechecker_suite()` +_TODO: Describe this rule: see issue [#44](https://github.com/Ericsson/rules_codechecker/issues/44)._ + +### `codechecker_config()` + +Using the Bazel rule `codechecker_config()` you can utilize a CodeChecker [configuration file](https://github.com/Ericsson/codechecker/blob/master/docs/config_file.md). + +First, include the rule in your BUILD file: + +```python +load( + "@rules_codechecker//:defs.bzl", + "codechecker_config" +) +``` + +Create a CodeChecker configuration file e.g. `config.json` (see example [test/config.json](test/config.json)) and parse it using `codechecker_config()`. + +```python +codechecker_config( + name = "your_codechecker_config", + config_file = ":config.json" +) +``` + +Alternatively, you can assemble a CodeChecker configuration without a config file using the rule: + +```python +codechecker_config( + name = "your_codechecker_config", + analyze = [ + "--enable=bugprone-dangling-handle", + "--enable=bugprone-fold-init-type", + "--enable=misc-non-copyable-objects", + "--report-hash=context-free-v2", + ] +) +``` + +You can now configure your `codechecker_suite()` and `codechecker_test()` targets using the above configuration: + +```python +codechecker_test( + name = "your_codechecker_rule_name", + config = "your_codechecker_config", + targets = [ + "your_target", + ], +) +``` + +## CodeChecker independent rules + +The following rules are _not_ using CodeChecker. + +### Clang-tidy: `clang_tidy_test()` + +The Bazel rule `clang_tidy_test()` runs clang-tidy natively without CodeChecker. +To use it, add the following to your BUILD file: + +```python +load( + "@rules_codechecker//:defs.bzl", + "clang_tidy_test", +) + +clang_tidy_test( + name = "your_rule_name", + targets = [ + "your_target", + ], +) +``` + +### Clang Static Analyzer: `clang_analyze_test()` + +The Bazel rule `clang_analyze_test()` runs The Clang Static Analyzer +natively without CodeChecker. +To use it, add the following to your BUILD file: + +```python +load( + "@rules_codechecker//:defs.bzl", + "clang_analyze_test", +) + +clang_analyze_test( + name = "your_rule_name", + targets = [ + "your_target", + ], +) +``` + +> [!Note] +> Currently `clang_analyze_test()` rule does not support CTU (Cross Translation Unit) analysis. + +### Generating a compilation database: `compile_commands()` + +As generating a compilation database for C/C++ is a known pain point for bazel, this repository defines the Bazel rule `compile_commands()` rule which can be used independently of CodeChecker. The implementation is based on https://github.com/grailbio/bazel-compilation-database with some fixes on some tricky edge cases. To use it, include the following in your BUILD file: + +```python +load( + "@rules_codechecker//:defs.bzl", + "compile_commands", +) +``` + +Then use `compile_commands()` rule passing build targets: + +```python +compile_commands( + name = "your_compile_commands_rule_name", + targets = [ + "your_target", + ], +) +``` +You can find the generated `compile_commands.json` under `bazel-bin/`. + +## Experimental rules + +### Cross-translation unit analysis via the Clang Static Analyzer: `clang_ctu_test()` +> [!IMPORTANT] +> The rule is still in prototype status and is subject to changes or removal without notice. See [#32](https://github.com/Ericsson/rules_codechecker/issues/32). +> We are also actively pursuing better CTU support _using_ CodeChecker. + +The Bazel rule `clang_analyze_test()` runs The Clang Static Analyzer with [cross translation unit analysis](https://clang.llvm.org/docs/analyzer/user-docs/CrossTranslationUnit.html) analysis without CodeChecker. To use it, add the following to your BUILD file: + +```python +load( + "@rules_codechecker//src:clang_ctu.bzl", + "clang_ctu_test", +) + +clang_ctu_test( + name = "your_clang_ctu_rule_name", + targets = [ + "your_target", + ], +) +``` + +Examples +-------- + +In [test/BUILD](test/BUILD) you can find examples for `codechecker_test()` +and for `compile_commands()` rules. + +For instance see targets `codechecker_pass` and `compile_commands_pass`. + +Run all test Bazel targets: + + bazel test ... + +After that you can find all artifacts in `bazel-bin` directory: + + # All codechecker_pass artifacts + ls bazel-bin/test/codechecker_pass/ + + # compile_commands.json for compile_commands_pass + cat bazel-bin/test/compile_commands_pass/compile_commands.json + +Toolchains +---------- + +The previous rules locate the CodeChecker, Clang and clang-tidy executables through a +Bazel [toolchain](https://bazel.build/extending/toolchains). Modeling the tools +as a toolchain means the analysis rule (`codechecker_test`) never hardcode binary paths: +Bazel resolves the correct tools at build time, and you can override them +per-project or per-platform without touching the rules themselves. + +### The default toolchain + +For most users no setup is required. `rules_codechecker` ships with a module +extension that provisions a default set of tools and a pre-registered +toolchain. + +> [!NOTE] +> The default tools resolve to the `CodeChecker`, `clang` and `clang-tidy` +> binaries available from PATH on your system (see the [Prerequisites](#prerequisites)). + +To enable it, add the following to your `MODULE.bazel`: + +```python +codechecker_extension = use_extension( + "@rules_codechecker//src:tools.bzl", + "module_register_default_codechecker_tools", +) +use_repo(codechecker_extension, "default_codechecker_tools") +register_toolchains("@rules_codechecker//src:codechecker_local_toolchain") +``` + +### Providing your own tools + +If you don't want the default system tools -- for example to pin a specific +CodeChecker version or point at a custom build —- you can define and register your own toolchain. + +First, you will have to create or obtain labels for codechecker, clang and clang-tidy. + +You may create such a label like this: +```python +filegroup( + name = "clang", + srcs = ["/usr/bin/clang"], + visibility = ["//visibility:public"], +) +``` + +Then define an implementation in a BUILD file with `codechecker_toolchain()`: + +```python +load( + "@rules_codechecker//:defs.bzl", + "codechecker_toolchain", +) + +codechecker_toolchain( + name = "codechecker_custom", + clang_tidy = "//example_target:clang-tidy", + clangsa = "//example_target:clang", + codechecker = "//example_target:CodeChecker", +) + +toolchain( + name = "codechecker_custom_toolchain", + toolchain = ":codechecker_custom", + toolchain_type = "@rules_codechecker//src:toolchain_type", + # Optionally constrain which execution platform this applies to: + # exec_compatible_with = ["@platforms//os:linux"], +) +``` +Finally register it in your `MODULE.bazel`: +```python +register_toolchains("//path/to:codechecker_custom_toolchain") +``` + +[!NOTE] +> Toolchains you register yourself take precedence over the default one if registered earlier.