-
Notifications
You must be signed in to change notification settings - Fork 4
Introduce CodeChecker toolchain #226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1b6d643
78acf88
3b6ec42
3c1331a
93dd1e4
bb67ef7
b1a7210
fb6fc1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -427,3 +427,83 @@ After that you can find all artifacts in `bazel-bin` directory: | |
|
|
||
| # 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") | ||
| ``` | ||
|
|
||
| Or the following to your `WORKSPACE`: | ||
|
|
||
| ```python | ||
| load( | ||
| "@rules_codechecker//src:tools.bzl", | ||
| "register_default_codechecker_tools", | ||
| ) | ||
|
|
||
| register_default_codechecker_tools() | ||
| register_toolchains( | ||
| "//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, define an implementation in a BUILD file with `codechecker_toolchain()`: | ||
|
|
||
| ```python | ||
| load( | ||
| "@rules_codechecker//src:codechecker_toolchain.bzl", | ||
| "codechecker_toolchain", | ||
| ) | ||
|
|
||
| codechecker_toolchain( | ||
| name = "codechecker_custom", | ||
| clang_tidy_binary = "@my_tools//:clang-tidy", | ||
| clangsa_binary = "@my_tools//:clang", | ||
| codechecker_binary = "@my_tools//:CodeChecker", | ||
|
Comment on lines
+490
to
+492
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The description and examples are missing for |
||
| ) | ||
|
|
||
| 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` (or `WORKSPACE`): | ||
| ```python | ||
| register_toolchains("//path/to:codechecker_custom_toolchain") | ||
| ``` | ||
|
|
||
| [!NOTE] | ||
| > Toolchains you register yourself take precedence over the default one if registered earlier. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,7 +29,7 @@ | |
|
|
||
| EXECUTION_MODE = "{Mode}" | ||
| VERBOSITY = "{Verbosity}" | ||
| CODECHECKER_PATH = "{codechecker_bin}" | ||
| CODECHECKER_PATH = os.path.realpath("{codechecker_bin}") | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So... we call |
||
| CLANG_PATH = "{clang_bin}" | ||
| CLANG_TIDY_PATH = "{clang_tidy_bin}" | ||
| CODECHECKER_SKIPFILE = "{codechecker_skipfile}" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| """ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As we discussed, probably we do not need prefix "codechecker" in the file name. |
||
| This file provides the toolchain rule for CodeChecker | ||
| """ | ||
|
|
||
| CodeCheckerInfo = provider( | ||
| doc = "This provider provides the executable path for CodeChecker and its related tools", | ||
| fields = { | ||
| "clang_tidy_bin": "clang-tidy executable", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need suffix "_bin"? Does it have any meaning? |
||
| "clangsa_bin": "Clang executable", | ||
| "codechecker_bin": "CodeChecker executable", | ||
| }, | ||
| ) | ||
|
|
||
| def _codechecker_toolchain_impl(ctx): | ||
| toolchain_info = platform_common.ToolchainInfo( | ||
| codecheckerinfo = CodeCheckerInfo( | ||
| codechecker_bin = ctx.executable.codechecker_binary, | ||
| clang_tidy_bin = ctx.executable.clang_tidy_binary, | ||
| clangsa_bin = ctx.executable.clangsa_binary, | ||
| ), | ||
| ) | ||
| return [toolchain_info] | ||
|
|
||
| codechecker_toolchain = rule( | ||
| implementation = _codechecker_toolchain_impl, | ||
| attrs = { | ||
| "clang_tidy_binary": attr.label( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same question: "_binary" - do we need? |
||
| doc = "clang-tidy executable", | ||
| allow_single_file = True, | ||
| executable = True, | ||
| cfg = "exec", | ||
| ), | ||
| "clangsa_binary": attr.label( | ||
| doc = "clang executable", | ||
| allow_single_file = True, | ||
| executable = True, | ||
| cfg = "exec", | ||
| ), | ||
| "codechecker_binary": attr.label( | ||
| doc = "CodeChecker executable", | ||
| allow_single_file = True, | ||
| executable = True, | ||
| cfg = "exec", | ||
| ), | ||
| }, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,11 +59,16 @@ def _run_code_checker( | |
| content = "\n".join(ctx.attr.skip), | ||
| ) | ||
|
|
||
| info = ctx.toolchains["//src:toolchain_type"].codecheckerinfo | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we discussed that to get rid of "src" you may try alias. (I havent tried myself though :) ) |
||
|
|
||
| if "--ctu" in options: | ||
| inputs = [ | ||
| compile_commands_json, | ||
| config_file, | ||
| config, | ||
| info.codechecker_bin, | ||
| info.clangsa_bin, | ||
| info.clang_tidy_bin, | ||
| ] + sources_and_headers | ||
| else: | ||
| # NOTE: we collect only headers, so CTU may not work! | ||
|
|
@@ -73,24 +78,32 @@ def _run_code_checker( | |
| config_file, | ||
| src, | ||
| config, | ||
| info.codechecker_bin, | ||
| info.clangsa_bin, | ||
| info.clang_tidy_bin, | ||
| ], transitive = [headers]) | ||
|
|
||
| outputs = [clang_tidy_plist, clangsa_plist, codechecker_log] | ||
|
|
||
| analyzer_output_paths = "clangsa," + clangsa_plist.path + \ | ||
| ";clang-tidy," + clang_tidy_plist.path | ||
|
|
||
| analyzer_executables = "clangsa:" + info.clangsa_bin.path + \ | ||
| ";clang-tidy:" + info.clang_tidy_bin.path | ||
|
|
||
| # Action to run CodeChecker for a file | ||
| ctx.actions.run( | ||
| inputs = inputs, | ||
| outputs = outputs, | ||
| executable = ctx.outputs.per_file_script, | ||
| arguments = [ | ||
| info.codechecker_bin.path, | ||
| data_dir, | ||
| src.path, | ||
| codechecker_log.path, | ||
| config.path, | ||
| analyzer_output_paths, | ||
| analyzer_executables, | ||
| ], | ||
| mnemonic = "CodeChecker", | ||
| use_default_shell_env = True, | ||
|
|
@@ -258,4 +271,5 @@ per_file_test = rule( | |
| "test_script": "%{name}/test_script.sh", | ||
| }, | ||
| test = True, | ||
| toolchains = ["//src:toolchain_type"], | ||
| ) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what is the meaning of "locat"?
Is there a "global" alternative?