From 18c6883e4cdc59ef1510b7eb825584b6dc076c5d Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Mon, 1 Dec 2025 13:41:27 +0100 Subject: [PATCH 1/6] Add support for config files in per_file rule --- src/per_file.bzl | 41 ++++++++++++++++++++++++++++++++++++----- src/per_file_script.py | 19 +++++++++---------- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/per_file.bzl b/src/per_file.bzl index 67d51538..3291a243 100644 --- a/src/per_file.bzl +++ b/src/per_file.bzl @@ -19,7 +19,15 @@ for each translation unit. load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") -load("@codechecker_bazel//src:tools.bzl", "warning", "source_attr") +load("@codechecker_bazel//src:tools.bzl", "warning") +load( + "compile_commands.bzl", + "platforms_transition", +) +load( + "@codechecker_bazel//src:codechecker_config.bzl", + "get_config_file" +) def _run_code_checker( ctx, @@ -27,6 +35,8 @@ def _run_code_checker( arguments, label, options, + config_file, + env_vars, compile_commands_json, compilation_context, sources_and_headers): @@ -43,11 +53,11 @@ def _run_code_checker( codechecker_log = ctx.actions.declare_file(codechecker_log_file_name) if "--ctu" in options: - inputs = [compile_commands_json] + sources_and_headers + inputs = [compile_commands_json, config_file] + sources_and_headers else: # NOTE: we collect only headers, so CTU may not work! headers = depset([src], transitive = [compilation_context.headers]) - inputs = depset([compile_commands_json, src], transitive = [headers]) + inputs = depset([compile_commands_json, config_file, src], transitive = [headers]) outputs = [clang_tidy_plist, clangsa_plist, codechecker_log] @@ -277,7 +287,7 @@ def _collect_all_sources_and_headers(ctx): sources_and_headers = all_files + headers.to_list() return sources_and_headers -def _create_wrapper_script(ctx, options, compile_commands_json): +def _create_wrapper_script(ctx, options, compile_commands_json, config_file): options_str = "" for item in options: options_str += item + " " @@ -289,6 +299,7 @@ def _create_wrapper_script(ctx, options, compile_commands_json): "{PythonPath}": ctx.attr._python_runtime[PyRuntimeInfo].interpreter_path, "{compile_commands_json}": compile_commands_json.path, "{codechecker_args}": options_str, + "{config_file}": config_file.path, }, ) @@ -297,7 +308,8 @@ def _per_file_impl(ctx): sources_and_headers = _collect_all_sources_and_headers(ctx) options = ctx.attr.default_options + ctx.attr.options all_files = [compile_commands_json] - _create_wrapper_script(ctx, options, compile_commands_json) + config_file, env_vars = get_config_file(ctx) + _create_wrapper_script(ctx, options, compile_commands_json, config_file) for target in ctx.attr.targets: if not CcInfo in target: continue @@ -314,6 +326,8 @@ def _per_file_impl(ctx): args, ctx.attr.name, options, + config_file, + env_vars, compile_commands_json, compilation_context, sources_and_headers, @@ -363,6 +377,15 @@ per_file_test = rule( ], doc = "List of compilable targets which should be checked.", ), + "config": attr.label( + default = None, + cfg = platforms_transition, + doc = "CodeChecker configuration", + ), + "platform": attr.string( + default = "", #"@platforms//os:linux", + doc = "Platform to build for", + ), "_per_file_script_template": attr.label( default = ":per_file_script.py", allow_single_file = True, @@ -370,6 +393,10 @@ per_file_test = rule( "_python_runtime": attr.label( default = "@default_python_tools//:py3_runtime", ), + "_whitelist_function_transition": attr.label( + default = "@bazel_tools//tools/whitelists/function_transition_whitelist", + doc = "needed for transitions", + ), }, outputs = { "test_script": "%{name}/test_script.sh", @@ -382,12 +409,16 @@ per_file_test = rule( def code_checker_test( name, targets, + config = None, options = [], tags = [], + **kwargs ): per_file_test( name = name, options = options, targets = targets, + config = config, tags = tags, + **kwargs ) diff --git a/src/per_file_script.py b/src/per_file_script.py index 46bd13b4..5c02e2a3 100644 --- a/src/per_file_script.py +++ b/src/per_file_script.py @@ -32,6 +32,7 @@ COMPILE_COMMANDS_JSON: str = "{compile_commands_json}" COMPILE_COMMANDS_ABSOLUTE: str = f"{COMPILE_COMMANDS_JSON}.abs" CODECHECKER_ARGS: str = "{codechecker_args}" +CONFIG_FILE: str = "{config_file}" def parse_args(): @@ -82,10 +83,15 @@ def _run_codechecker() -> None: """ Runs CodeChecker analyze """ - log( - f"CodeChecker command: CodeChecker analyze {CODECHECKER_ARGS} \ -{COMPILE_COMMANDS_ABSOLUTE} --output={DATA_DIR} --file=*/{FILE_PATH}\n" + codechecker_cmd: list[str] = ( + ["CodeChecker", "analyze"] + + CODECHECKER_ARGS.split() + + ["--output=" + DATA_DIR] # type: ignore + + ["--file=*/" + FILE_PATH] # type: ignore + + ["--config=" + CONFIG_FILE] + + [COMPILE_COMMANDS_ABSOLUTE] ) + log(f"CodeChecker command: {' '.join(codechecker_cmd)}\n") log("===-----------------------------------------------------===\n") log(" CodeChecker error log \n") log("===-----------------------------------------------------===\n") @@ -99,13 +105,6 @@ def _run_codechecker() -> None: ) log(result.stdout) - codechecker_cmd: list[str] = ( - ["CodeChecker", "analyze"] - + CODECHECKER_ARGS.split() - + ["--output=" + DATA_DIR] # type: ignore - + ["--file=*/" + FILE_PATH] # type: ignore - + [COMPILE_COMMANDS_ABSOLUTE] - ) try: with open(LOG_FILE, "a") as log_file: # type: ignore From fd7ae09be148fd50a4ece7fcecbf6bf734983731 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 2 Dec 2025 12:27:31 +0100 Subject: [PATCH 2/6] Activate tests --- test/unit/config/BUILD | 6 ++---- test/unit/config/test_config.py | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/test/unit/config/BUILD b/test/unit/config/BUILD index 2447abda..b2b8493e 100644 --- a/test/unit/config/BUILD +++ b/test/unit/config/BUILD @@ -90,8 +90,7 @@ codechecker_test( codechecker_test( name = "per_file_test_json", - #config = "config_json", #TODO: uncomment - # complains that per_file doesn't have a config attribute + config = "config_json", targets = [ "test_zero", ], @@ -101,8 +100,7 @@ codechecker_test( codechecker_test( name = "per_file_test_yaml", - #config = "config_yaml", #TODO: uncomment - # complains that per_file doesn't have a config attribute + config = "config_yaml", targets = [ "test_zero", ], diff --git a/test/unit/config/test_config.py b/test/unit/config/test_config.py index 145bcf59..4b8b911a 100644 --- a/test/unit/config/test_config.py +++ b/test/unit/config/test_config.py @@ -95,15 +95,13 @@ def test_per_file_test_json(self): "bazel test //test/unit/config:per_file_test_json" ) # Should not find the division by zero bug - self.assertEqual(ret, 3) # TODO: Change to 0 - # since CodeChecker won't find the division by zero bug + self.assertEqual(ret, 0) copied_config = os.path.join( self.BAZEL_BIN_DIR, # type: ignore "per_file_test_json", "config.json" ) - self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True - # Before the patch config files aren't supported in per_file + self.assertTrue(os.path.exists(copied_config)) def test_per_file_test_yaml(self): """Test: bazel test //test/unit/config:per_file_test_yaml""" From b2d896352a4e5713f57f8812cadb60adcbf90cf8 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 2 Dec 2025 12:38:24 +0100 Subject: [PATCH 3/6] Fix script --- src/per_file_script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/per_file_script.py b/src/per_file_script.py index 5c02e2a3..47bdafb4 100644 --- a/src/per_file_script.py +++ b/src/per_file_script.py @@ -88,7 +88,7 @@ def _run_codechecker() -> None: + CODECHECKER_ARGS.split() + ["--output=" + DATA_DIR] # type: ignore + ["--file=*/" + FILE_PATH] # type: ignore - + ["--config=" + CONFIG_FILE] + + ["--config", CONFIG_FILE] + [COMPILE_COMMANDS_ABSOLUTE] ) log(f"CodeChecker command: {' '.join(codechecker_cmd)}\n") From d0e7a3526e74607582047aee595886f1846de687 Mon Sep 17 00:00:00 2001 From: "F.Tibor" Date: Tue, 2 Dec 2025 14:36:11 +0100 Subject: [PATCH 4/6] Enable the final test --- test/unit/config/test_config.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/unit/config/test_config.py b/test/unit/config/test_config.py index 4b8b911a..72acd4a5 100644 --- a/test/unit/config/test_config.py +++ b/test/unit/config/test_config.py @@ -109,15 +109,13 @@ def test_per_file_test_yaml(self): "bazel test //test/unit/config:per_file_test_yaml" ) # Should not find the division by zero bug - self.assertEqual(ret, 3) # TODO: Change to 0 - # since CodeChecker won't find the division by zero bug + self.assertEqual(ret, 0) copied_config = os.path.join( self.BAZEL_BIN_DIR, # type: ignore "per_file_test_yaml", "config.yaml" ) - self.assertFalse(os.path.exists(copied_config)) # TODO: Set to True - # Before the patch config files aren't supported in per_file + self.assertTrue(os.path.exists(copied_config)) if __name__ == "__main__": From e9b6eb1d86f0a0531f2b98d92570c58c44ed9eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Mon, 12 Jan 2026 10:34:53 +0100 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: F.Tibor --- src/per_file.bzl | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/per_file.bzl b/src/per_file.bzl index 3291a243..f57edf30 100644 --- a/src/per_file.bzl +++ b/src/per_file.bzl @@ -379,13 +379,8 @@ per_file_test = rule( ), "config": attr.label( default = None, - cfg = platforms_transition, doc = "CodeChecker configuration", ), - "platform": attr.string( - default = "", #"@platforms//os:linux", - doc = "Platform to build for", - ), "_per_file_script_template": attr.label( default = ":per_file_script.py", allow_single_file = True, @@ -393,10 +388,7 @@ per_file_test = rule( "_python_runtime": attr.label( default = "@default_python_tools//:py3_runtime", ), - "_whitelist_function_transition": attr.label( - default = "@bazel_tools//tools/whitelists/function_transition_whitelist", - doc = "needed for transitions", - ), + }, outputs = { "test_script": "%{name}/test_script.sh", From d25337b1e767643f5aef2d086251581a5b00da91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Mon, 12 Jan 2026 11:15:39 +0100 Subject: [PATCH 6/6] Get rid of platforms_transition and load source_attr --- src/per_file.bzl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/per_file.bzl b/src/per_file.bzl index f57edf30..7b187910 100644 --- a/src/per_file.bzl +++ b/src/per_file.bzl @@ -19,11 +19,7 @@ for each translation unit. load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") -load("@codechecker_bazel//src:tools.bzl", "warning") -load( - "compile_commands.bzl", - "platforms_transition", -) +load("@codechecker_bazel//src:tools.bzl", "warning", "source_attr") load( "@codechecker_bazel//src:codechecker_config.bzl", "get_config_file"