From 1e2f79431ea0a0cea9a4461c1077367c7cc5756e Mon Sep 17 00:00:00 2001 From: Mathias Laurin Date: Mon, 15 Sep 2025 12:24:07 +0200 Subject: [PATCH 1/3] Update bazel_skylib to 1.8.1 for `rules/directory` --- MODULE.bazel | 2 +- example/MODULE.bazel | 2 +- example/WORKSPACE.bazel | 11 ++++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index fb5c5731..9a6839c8 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -14,7 +14,7 @@ bazel_dep(name = "aspect_rules_js", version = "1.40.0") bazel_dep(name = "aspect_tools_telemetry", version = "0.2.8") bazel_dep(name = "bazel_features", version = "1.0.0") bazel_dep(name = "bazel_lib", version = "3.0.0-rc.0") -bazel_dep(name = "bazel_skylib", version = "1.4.2") +bazel_dep(name = "bazel_skylib", version = "1.8.1") bazel_dep(name = "platforms", version = "0.0.7") bazel_dep(name = "rules_multirun", version = "0.9.0") bazel_dep(name = "rules_multitool", version = "0.11.0") diff --git a/example/MODULE.bazel b/example/MODULE.bazel index b8b2d81a..080a5d8d 100644 --- a/example/MODULE.bazel +++ b/example/MODULE.bazel @@ -11,7 +11,7 @@ bazel_dep(name = "bazel_lib", version = "3.0.0-rc.0") bazel_dep(name = "rules_buf", version = "0.5.2") bazel_dep(name = "rules_dotnet", version = "0.20.5") bazel_dep(name = "bazel_features", version = "1.29.0") -bazel_dep(name = "bazel_skylib", version = "1.4.2") +bazel_dep(name = "bazel_skylib", version = "1.8.1") bazel_dep(name = "toolchains_llvm", version = "1.1.2") bazel_dep(name = "toolchains_protoc", version = "0.3.7") bazel_dep(name = "rules_java", version = "8.5.0") diff --git a/example/WORKSPACE.bazel b/example/WORKSPACE.bazel index d7fd57db..9cb35ec0 100644 --- a/example/WORKSPACE.bazel +++ b/example/WORKSPACE.bazel @@ -180,7 +180,16 @@ load("@buildifier_prebuilt//:deps.bzl", "buildifier_prebuilt_deps") buildifier_prebuilt_deps() -load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") +http_archive( + name = "bazel_skylib_gh", + sha256 = "51b5105a760b353773f904d2bbc5e664d0987fbaf22265164de65d43e910d8ac", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.8.1/bazel-skylib-1.8.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.8.1/bazel-skylib-1.8.1.tar.gz", + ], +) + +load("@bazel_skylib_gh//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() From 8e5b7720fbc59b76a13dacd54daba0d7e5c8a069 Mon Sep 17 00:00:00 2001 From: Mathias Laurin Date: Fri, 18 Jul 2025 22:13:52 +0200 Subject: [PATCH 2/3] [feat] clang-tidy: add optional gcc-install-dir arg Without the argument, clang (clang-tidy) discovers a gcc installation automatically on the system, for example, ``` % clang -v Ubuntu clang version 18.1.8 (++20240731024944+3b5b5c1ec4a3-1~exp1~20240731145000.144) Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/11 Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/12 Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/13 Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/13 ``` However, users may want to switch off the discovery and specify a version, exactly. ``` % clang -v --gcc-install-dir=/usr/lib/gcc/x86_64-linux-gnu/12 Ubuntu clang version 18.1.8 (++20240731024944+3b5b5c1ec4a3-1~exp1~20240731145000.144) Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12 ``` This is especially relevant for, but not limited to, hermetic toolchains. See also This patch ports https://github.com/erenon/bazel_clang_tidy/pull/88 to rules_lint. --- lint/clang_tidy.bzl | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lint/clang_tidy.bzl b/lint/clang_tidy.bzl index 202cd6fe..abc51fbf 100644 --- a/lint/clang_tidy.bzl +++ b/lint/clang_tidy.bzl @@ -37,6 +37,7 @@ clang_tidy = lint_clang_tidy_aspect( ``` """ +load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo") load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") load("//lint/private:lint_aspect.bzl", "LintOptionsInfo", "OPTIONAL_SARIF_PARSER_TOOLCHAIN", "OUTFILE_FORMAT", "noop_lint_action", "output_files", "parse_to_sarif_action", "patch_and_output_files") @@ -262,6 +263,14 @@ def _get_args(ctx, compilation_context, srcs): def _get_compiler_args(ctx, compilation_context, srcs): # add args specified by the toolchain, on the command line and rule copts args = [] + + if ctx.attr._gcc_install_dir: + gcc_install_dir = ctx.attr._gcc_install_dir[0].files.to_list() + if len(gcc_install_dir) > 1: + fail("gcc_install_dir must contain at most one directory") + for dir in gcc_install_dir: + args.append("--gcc-install-dir=" + dir.path) + rule_flags = ctx.rule.attr.copts if hasattr(ctx.rule.attr, "copts") else [] sources_are_cxx = _is_cxx(srcs[0]) if (sources_are_cxx): @@ -409,7 +418,15 @@ def _clang_tidy_aspect_impl(target, ctx): parse_to_sarif_action(ctx, _MNEMONIC, raw_machine_report, outputs.machine.out) return [info] -def lint_clang_tidy_aspect(binary, configs = [], global_config = [], header_filter = "", lint_target_headers = False, angle_includes_are_system = True, verbose = False): +def lint_clang_tidy_aspect( + binary, + configs = [], + global_config = [], + gcc_install_dir = [], + header_filter = "", + lint_target_headers = False, + angle_includes_are_system = True, + verbose = False): """A factory function to create a linter aspect. Args: @@ -427,6 +444,8 @@ def lint_clang_tidy_aspect(binary, configs = [], global_config = [], header_filt files which may be used for formatting fixes. global_config: label of a single global .clang-tidy file to pass to clang-tidy on the command line. This will cause clang-tidy to ignore any other config files in the source directories. + gcc_install_dir: optional, label of a `Directory` from the skylib library pointing to the gcc install + directory. The argument is passed to the underlying clang as `--gcc-install-dir`. header_filter: optional, set to a posix regex to supply to clang-tidy with the -header-filter option lint_target_headers: optional, set to True to pass a pattern that includes all headers with the target's directory prefix. This crude control may include headers from the linted target in the results. If @@ -455,6 +474,10 @@ def lint_clang_tidy_aspect(binary, configs = [], global_config = [], header_filt default = global_config, allow_files = True, ), + "_gcc_install_dir": attr.label_list( + default = gcc_install_dir, + providers = [DirectoryInfo], + ), "_lint_target_headers": attr.bool( default = lint_target_headers, ), From 58899ccf532c183cbb9c50bfb785d5ee4c3d0f69 Mon Sep 17 00:00:00 2001 From: Mathias Laurin Date: Wed, 23 Jul 2025 09:28:32 +0200 Subject: [PATCH 3/3] [feat] clang-tidy: add deps argument This partially ports https://github.com/erenon/bazel_clang_tidy/commit/b8c0567 to extend the support of hermetic toolchains. The `deps` argument lets users control the visibility of the hermetic gcc install during the clang-tidy run. --- lint/clang_tidy.bzl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lint/clang_tidy.bzl b/lint/clang_tidy.bzl index abc51fbf..e0854679 100644 --- a/lint/clang_tidy.bzl +++ b/lint/clang_tidy.bzl @@ -51,6 +51,8 @@ def _gather_inputs(ctx, compilation_context, srcs): inputs = srcs + ctx.files._configs if (any(ctx.files._global_config)): inputs.append(ctx.files._global_config[0]) + for dep in ctx.files._deps: + inputs.append(dep) return depset(inputs, transitive = [compilation_context.headers]) def _toolchain_env(ctx, user_flags, action_name = ACTION_NAMES.cpp_compile): @@ -423,6 +425,7 @@ def lint_clang_tidy_aspect( configs = [], global_config = [], gcc_install_dir = [], + deps = [], header_filter = "", lint_target_headers = False, angle_includes_are_system = True, @@ -444,6 +447,7 @@ def lint_clang_tidy_aspect( files which may be used for formatting fixes. global_config: label of a single global .clang-tidy file to pass to clang-tidy on the command line. This will cause clang-tidy to ignore any other config files in the source directories. + deps: labels of additional dependencies used during the clang-tidy run. gcc_install_dir: optional, label of a `Directory` from the skylib library pointing to the gcc install directory. The argument is passed to the underlying clang as `--gcc-install-dir`. header_filter: optional, set to a posix regex to supply to clang-tidy with the -header-filter option @@ -474,6 +478,9 @@ def lint_clang_tidy_aspect( default = global_config, allow_files = True, ), + "_deps": attr.label_list( + default = deps, + ), "_gcc_install_dir": attr.label_list( default = gcc_install_dir, providers = [DirectoryInfo],