From 528b3086319626298436add380b4db944a6731f9 Mon Sep 17 00:00:00 2001 From: Paul Quiring Date: Mon, 13 Jul 2026 14:35:43 +0200 Subject: [PATCH 1/2] Add pre-commit --- .clang-format | 48 ---- .clang-tidy | 2 + .clang_format | 5 + .github/workflows/format.yml | 12 +- .pre-commit-config.yaml | 62 +++++ .vscode/tasks.json | 2 +- BUILD | 66 +++++ MODULE.bazel | 34 ++- MODULE.bazel.lock | 237 ++++++++++++++++++ cr_checker_exclusion | 0 externals/acl/BUILD | 13 + externals/acl/acl.BUILD | 13 + externals/ipc_dropin/BUILD | 13 + .../include/ipc_dropin/ringbuffer.hpp | 13 + .../ipc_dropin/include/ipc_dropin/socket.hpp | 13 + patches/BUILD | 5 + .../hedron_compile_commands_env_vars.patch | 11 + patches/score_bazel_tools.patch | 6 + patches/score_bazel_tools_python.patch | 6 + scripts/config_mapping/BUILD | 13 + scripts/config_mapping/config.bzl | 13 + scripts/config_mapping/integration_tests.py | 12 + scripts/config_mapping/lifecycle_config.py | 12 + scripts/config_mapping/tests/BUILD | 13 + scripts/config_mapping/unit_tests.py | 13 + scripts/generate_cpp_compile_commands.sh | 16 +- scripts/generate_rust_analyzer_support.sh | 15 +- scripts/run_clang_tidy_precommit.py | 99 ++++++++ tests/integration/BUILD | 2 + .../integration/switch_run_target/common.hpp | 13 + 30 files changed, 719 insertions(+), 63 deletions(-) delete mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .clang_format create mode 100644 .pre-commit-config.yaml create mode 100644 cr_checker_exclusion create mode 100644 patches/BUILD create mode 100644 patches/hedron_compile_commands_env_vars.patch create mode 100644 patches/score_bazel_tools.patch create mode 100644 patches/score_bazel_tools_python.patch create mode 100644 scripts/run_clang_tidy_precommit.py diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 900517a28..000000000 --- a/.clang-format +++ /dev/null @@ -1,48 +0,0 @@ -BasedOnStyle: Google -AccessModifierOffset: -2 -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: Empty -AllowShortCaseLabelsOnASingleLine: false -AllowShortEnumsOnASingleLine: false -# Empty is required in AllowShortFunctionsOnASingleLine over Inline because Inline contradicts with AUTOSAR rule A7-1-7 -# Such rule is no longer existing in MISRA C++:2023, once we are fully migrated to MISRA C++:2023, switching to Inline -# could be reconsidered -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: Empty -AllowShortLoopsOnASingleLine: false -BinPackArguments: false -BinPackParameters: false -BraceWrapping: - AfterCaseLabel: true - AfterClass: true - AfterControlStatement: Always - AfterEnum: true - AfterFunction: true - AfterNamespace: true - AfterObjCDeclaration: true - AfterStruct: true - AfterUnion: true - BeforeCatch: true - BeforeElse: true - IndentBraces: false -BreakBeforeBraces: Custom -ColumnLimit: 120 -DerivePointerAlignment: false -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^(<|")(assert|complex|ctype|errno|fenv|float|inttypes|iso646|limits|locale|math|setjmp|signal|stdalign|stdargh|stdatomic|stdbool|stddef|stdint|stdio|stdlib|stdnoreturn|string|tgmath|threads|time|uchar|wchar|wctype)\.h(>|")$' - Priority: 2 - - Regex: '^(<|")(cstdlib|csignal|csetjmp|cstdarg|typeinfo|typeindex|type_traits|bitset|functional|utility|ctime|chrono|cstddef|initializer_list|tuple|any|optional|variant|new|memory|scoped_allocator|memory_resource|climits|cfloat|cstdint|cinttypes|limits|exception|stdexcept|cassert|system_error|cerrno|cctype|cwctype|cstring|cwchar|cuchar|string|string_view|array|vector|deque|list|forward_list|set|map|unordered_set|unordered_map|stack|queue|algorithm|execution|teratorslibrary|iterator|cmath|complex|valarray|random|numeric|ratio|cfenv|iosfwd|ios|istream|ostream|iostream|fstream|sstream|strstream|iomanip|streambuf|cstdio|locale|clocale|codecvt|regex|atomic|thread|mutex|shared_mutex|future|condition_variable|filesystem|ciso646|ccomplex|ctgmath|cstdalign|cstdbool)(>|")$' - Priority: 3 - - Regex: '^(<|").*(>|")$' - Priority: 1 -IndentWidth: 4 -InsertNewlineAtEOF: true -KeepEmptyLinesAtTheStartOfBlocks: true -QualifierAlignment: Left -CommentPragmas: '^.*A2Lfactory:' ---- -# Make sure language specific settings are below the generic settings to be compatible to all languages. -Language: Cpp -Standard: c++17 diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..d63a95901 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,2 @@ +Checks: ' -*, bugprone-*, cert-*, clang-analyzer-core.*, clang-analyzer-cplusplus.*, clang-analyzer-security.*, cppcoreguidelines-pro-bounds-pointer-arithmetic, cppcoreguidelines-pro-type-cstyle-cast, hicpp-* ' +WarningsAsErrors: 'bugprone-*,cert-*,clang-analyzer-*,hicpp-*' diff --git a/.clang_format b/.clang_format new file mode 100644 index 000000000..857de2800 --- /dev/null +++ b/.clang_format @@ -0,0 +1,5 @@ +--- +BasedOnStyle: Google +ColumnLimit: 120 +IndentWidth: 4 +--- diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index a42d721f2..0f8ee7cd7 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -1,5 +1,5 @@ # ******************************************************************************* -# Copyright (c) 2025 Contributors to the Eclipse Foundation +# Copyright (c) 2026 Contributors to the Eclipse Foundation # # See the NOTICE file(s) distributed with this work for additional # information regarding copyright ownership. @@ -12,16 +12,14 @@ # ******************************************************************************* name: Formatting checks - +permissions: + contents: read + actions: write on: pull_request: types: [opened, reopened, synchronize] merge_group: types: [checks_requested] -env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: formatting-check: - uses: eclipse-score/cicd-workflows/.github/workflows/format.yml@c1c90b1a82a1fab0fc202979dde6686b2162d5a8 # v0.0.0 - with: - bazel-target: "test --lockfile_mode=error //:format.check" # optional, this is the default + uses: eclipse-score/cicd-workflows/.github/workflows/format.yml@f57b605a284ca117bcfd9f83ea427096faaac7d1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..462883cb4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,62 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +repos: + - repo: local + hooks: + - id: copyright-fix + name: //:copyright-fix + entry: bazel run //:copyright-fix + language: system + pass_filenames: false + - id: format-fix + name: //:format.fix + entry: bazel run //:format.fix + language: system + files: (BUILD|BUILD\.bazel|WORKSPACE|\.bazelrc|[^/]+\.(py|bzl|bazel|yaml|yml|rs))$ + pass_filenames: false + - repo: https://github.com/pocc/pre-commit-hooks + rev: v1.3.5 + hooks: + - id: clang-format + name: clang-format + # Run the tool binary directly so pre-commit's staged relative paths work. + # If clang-format cannot be found, the toolchain folder name likely changed. + entry: bazel-bin/external/toolchains_llvm++llvm+llvm_toolchain/clang-format -i + language: system + files: '\.(c|cc|cpp|h|hpp)$' + # all relevant files are currently excluded the format is not + # clarified yet, so we don't want to run clang-format on any files + exclude: | + (?x)^( + externals/| + examples/| + tests/| + score/ + ) + - id: clang-tidy + name: clang-tidy + # Run through a wrapper that sanitizes unsupported linker flags in + # compile_commands.json before invoking clang-tidy. + entry: ./scripts/run_clang_tidy_precommit.py + language: system + files: '\.(c|cc|cpp|h|hpp)$' + # all relevant files are currently excluded the checks are + # not clarified yet, so we don't want to run clang-tidy on any files + exclude: | + (?x)^( + externals/| + examples/| + tests/| + score/ + ) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 1713f9f06..10b932441 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,7 +5,7 @@ "label": "Refresh compile_commands.json", "type": "shell", "isBackground": true, - "command": "bazel run @hedron_compile_commands//:refresh_all", + "command": "bazel run //:generate_compile_commands -- --config=x86_64-linux", "problemMatcher": [], "group": { "kind": "build", diff --git a/BUILD b/BUILD index ddb344904..bfabff53d 100644 --- a/BUILD +++ b/BUILD @@ -11,11 +11,55 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands") load("@rules_python//python:pip.bzl", "compile_pip_requirements") +load("@score_bazel_tools_cc//quality:defs.bzl", "clang_format_config", "quality_clang_tidy_config") load("@score_docs_as_code//:docs.bzl", "docs") load("@score_tooling//:defs.bzl", "copyright_checker", "dash_license_checker", "rust_coverage_report", "setup_starpls", "use_format_targets") load("//:project_config.bzl", "PROJECT_CONFIG") +# Generate `compile_commands.json`. +# Required for `clangd` support. +refresh_compile_commands( + name = "generate_compile_commands", + exclude_external_sources = True, + target_compatible_with = ["@platforms//os:linux"], + targets = { + "//...": "", + }, +) + +quality_clang_tidy_config( + name = "clang_tidy_config", + additional_flags = [], + clang_tidy_binary = "@llvm_toolchain//:clang-tidy", + default_feature = "strict", + dependency_attributes = [ + "deps", + "srcs", + ], + excludes = ["external/"], + feature_mapping = { + "//:.clang-tidy": "strict", + }, + target_types = [ + "cc_library", + ], + unsupported_flags = [], + visibility = ["//visibility:public"], +) + +clang_format_config( + name = "clang_format_config", + config_file = "//:.clang_format", + excludes = ["external/"], + target_types = [ + "cc_binary", + "cc_library", + ], + visibility = ["//visibility:public"], +) + # In order to update the requirements, change the `requirements.in` file and run: # `bazel run //:requirements.update`. # This will update the `requirements_lock.txt` file. @@ -45,12 +89,34 @@ setup_starpls( copyright_checker( name = "copyright", srcs = [ + ".github", + "docs", "examples", + "externals", "score", + "scripts", + "tests", "//:BUILD", "//:MODULE.bazel", ], config = "@score_tooling//cr_checker/resources:config", + exclusion = "//:cr_checker_exclusion", + extensions = [ + "bazel", + "BUILD", + "bzl", + "c", + "cpp", + "h", + "hpp", + "ini", + "py", + "rs", + "rst", + "sh", + "yaml", + "yml", + ], template = "@score_tooling//cr_checker/resources:templates", visibility = ["//visibility:public"], ) diff --git a/MODULE.bazel b/MODULE.bazel index aa7bd2c10..a05d96f9a 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -22,6 +22,7 @@ bazel_dep(name = "rules_python", version = "1.8.5") bazel_dep(name = "rules_rust", version = "0.68.2-score") bazel_dep(name = "rules_cc", version = "0.2.17") bazel_dep(name = "rules_oci", version = "2.3.0") +bazel_dep(name = "rules_shell", version = "0.6.1") bazel_dep(name = "aspect_rules_lint", version = "2.3.0") bazel_dep(name = "buildifier_prebuilt", version = "8.5.1") bazel_dep(name = "platforms", version = "1.0.0") @@ -39,6 +40,20 @@ bazel_dep(name = "score_rust_policies", version = "0.0.5", dev_dependency = True bazel_dep(name = "score_cpp_policies", version = "0.0.1", dev_dependency = True) bazel_dep(name = "score_process", version = "1.6.0", dev_dependency = True) bazel_dep(name = "score_platform", version = "0.6.0", dev_dependency = True) +bazel_dep(name = "score_bazel_tools_cc", version = "0.1.0", dev_dependency = True) +single_version_override( + module_name = "score_bazel_tools_cc", + patch_strip = 0, + patches = ["//patches:score_bazel_tools.patch"], + version = "0.1.0", +) + +single_version_override( + module_name = "score_bazel_tools_python", + patch_strip = 0, + patches = ["//patches:score_bazel_tools_python.patch"], + version = "0.1.3", +) ## Configure the C++ toolchain bazel_dep(name = "score_bazel_cpp_toolchains", version = "0.5.4", dev_dependency = True) @@ -84,6 +99,18 @@ use_repo( "score_qcc_x86_64_toolchain_pkg", ) +# LLVM toolchain. +bazel_dep(name = "toolchains_llvm", version = "1.4.0") + +llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm") +llvm.toolchain( + llvm_version = "15.0.2", + stdlib = {"linux-x86_64": "stdc++"}, +) +use_repo(llvm, "llvm_toolchain") + +register_toolchains("@llvm_toolchain//:all") + # UTs on QNX bazel_dep(name = "score_qnx_unit_tests", version = "0.2.0", dev_dependency = True) bazel_dep(name = "score_rules_imagefs", version = "0.0.3", dev_dependency = True) @@ -165,8 +192,9 @@ bazel_dep(name = "score_baselibs", version = "0.2.9") bazel_dep(name = "hedron_compile_commands", dev_dependency = True) git_override( module_name = "hedron_compile_commands", - commit = "0e990032f3c5a866e72615cf67e5ce22186dcb97", + commit = "abb61a688167623088f8768cc9264798df6a9d10", + patch_strip = 1, + # Patch for support for Bazel 8.6.0. + patches = ["//patches:hedron_compile_commands_env_vars.patch"], remote = "https://github.com/hedronvision/bazel-compile-commands-extractor.git", - # Replace the commit hash (above) with the latest (https://github.com/hedronvision/bazel-compile-commands-extractor/commits/main). - # Even better, set up Renovate and let it do the work for you (see "Suggestion: Updates" in the README). ) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index ff73b75cd..94a14524c 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -460,6 +460,8 @@ "https://bcr.bazel.build/modules/tar.bzl/0.7.0/source.json": "9becb80306f42d4810bfa16379fb48aad0b01ce5342bc12fe47dcd6af3ac4d7a", "https://bcr.bazel.build/modules/toolchain_utils/1.0.2/MODULE.bazel": "9b8be503a4fcfd3b8b952525bff0869177a5234d5c35dc3e566b9f5ca2f755a1", "https://bcr.bazel.build/modules/toolchain_utils/1.0.2/source.json": "88769ec576dddacafd8cca4631812cf8eead89f10a29d9405d9f7a553de6bf87", + "https://bcr.bazel.build/modules/toolchains_llvm/1.4.0/MODULE.bazel": "05239402b7374293359c2f22806f420b75aa5d6f4b15a2eaa809a2c214d58b31", + "https://bcr.bazel.build/modules/toolchains_llvm/1.4.0/source.json": "229a516d282b17a82be54c6e3ae220a1b750fb55a8495567e5c7a9d09423f3e2", "https://bcr.bazel.build/modules/toolchains_protoc/0.2.1/MODULE.bazel": "2f08433ff5e659069b3a1abfee2377d68f510f2de1da50678ed992c455b4ff91", "https://bcr.bazel.build/modules/upb/0.0.0-20211020-160625a/MODULE.bazel": "6cced416be2dc5b9c05efd5b997049ba795e5e4e6fafbe1624f4587767638928", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", @@ -839,6 +841,10 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_bazel_platforms/0.1.1/MODULE.bazel": "236e5bdff6f2d6de6f96cc4f5f4b1bf2cd6137547ce279668a2dd4c54cd4236c", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_bazel_platforms/0.1.2/MODULE.bazel": "d1889bf36241521c5d5c401aaf1e98242a60f9cab9d223f8190e5d7087956e83", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_bazel_platforms/0.1.2/source.json": "549c18a968c1ab76135ad38fd15981fcc04d377a62f20e2e5e0b5faa9de2b01d", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_bazel_tools_cc/0.1.0/MODULE.bazel": "e859eef20dc2f08a58586197cc59f721c640dd8d49bdc820a584d577d33d82a6", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_bazel_tools_cc/0.1.0/source.json": "c22ba73ccb64d3bbd2177122d9b039c23c1c1cd0b9c7ea71103e8c43af2e4411", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_bazel_tools_python/0.1.3/MODULE.bazel": "02bd71d03010d7903412b2c98d25519a46af7ec6d9492270ec371c198e15caec", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_bazel_tools_python/0.1.3/source.json": "f87907b20372ca2c4ad15719cba03423577ed1ea8392c7373eb37f73499decce", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_cpp_policies/0.0.1/MODULE.bazel": "e9d8ecb12ebd8d1fb2af6cfc3ba136600953d951983ef1e710f2f589de69a8c6", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_cpp_policies/0.0.1/source.json": "75f76a0d1a1208a94cbb43fc6455fc943ac262f354cfbb245da4220447d4c7f6", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_cr_checker/0.2.2/MODULE.bazel": "dc36d9c35543db918c3fb5b93a8e684431f56c7c784cf2a1b90f35802a373c98", @@ -910,6 +916,7 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/tar.bzl/0.5.1/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/tar.bzl/0.7.0/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/toolchain_utils/1.0.2/MODULE.bazel": "not found", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/toolchains_llvm/1.4.0/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/toolchains_protoc/0.2.1/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/upb/0.0.0-20211020-160625a/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "not found", @@ -9618,6 +9625,157 @@ ] } }, + "@@score_bazel_tools_cc+//third_party:extensions.bzl%rules_python_pip_hub": { + "general": { + "bzlTransitiveDigest": "0GtHtP/Cq5COo0Le4EOEdPZFNuSL/G5HWrhbCt9KuXA=", + "usagesDigest": "+R/amEJVckS++BDZJeRqyMgNukHUula12//Pxk9ndw8=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "score_bazel_tools_cc_pip_hub": { + "repoRuleId": "@@score_bazel_tools_python+//bazel/rules:rules_python_pip_hub.bzl%rules_python_pip_hub", + "attributes": { + "deps_to_config_map": { + "@score_bazel_tools_cc_pip_3_8": "@score_bazel_tools_cc//bazel/toolchains/python:python_3_8", + "@score_bazel_tools_cc_pip_3_9": "@score_bazel_tools_cc//bazel/toolchains/python:python_3_9", + "@score_bazel_tools_cc_pip_3_10": "@score_bazel_tools_cc//bazel/toolchains/python:python_3_10", + "@score_bazel_tools_cc_pip_3_11": "@score_bazel_tools_cc//bazel/toolchains/python:python_3_11", + "@score_bazel_tools_cc_pip_3_12": "@score_bazel_tools_cc//bazel/toolchains/python:python_3_12" + }, + "requirements_in": "@@score_bazel_tools_cc+//third_party/pip:requirements.in" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_cc+", + "cc_compatibility_proxy", + "rules_cc++compatibility_proxy+cc_compatibility_proxy" + ], + [ + "rules_cc++compatibility_proxy+cc_compatibility_proxy", + "rules_cc", + "rules_cc+" + ], + [ + "rules_python+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "rules_python+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_python+", + "pypi__build", + "rules_python++config+pypi__build" + ], + [ + "rules_python+", + "pypi__click", + "rules_python++config+pypi__click" + ], + [ + "rules_python+", + "pypi__colorama", + "rules_python++config+pypi__colorama" + ], + [ + "rules_python+", + "pypi__importlib_metadata", + "rules_python++config+pypi__importlib_metadata" + ], + [ + "rules_python+", + "pypi__installer", + "rules_python++config+pypi__installer" + ], + [ + "rules_python+", + "pypi__more_itertools", + "rules_python++config+pypi__more_itertools" + ], + [ + "rules_python+", + "pypi__packaging", + "rules_python++config+pypi__packaging" + ], + [ + "rules_python+", + "pypi__pep517", + "rules_python++config+pypi__pep517" + ], + [ + "rules_python+", + "pypi__pip", + "rules_python++config+pypi__pip" + ], + [ + "rules_python+", + "pypi__pip_tools", + "rules_python++config+pypi__pip_tools" + ], + [ + "rules_python+", + "pypi__pyproject_hooks", + "rules_python++config+pypi__pyproject_hooks" + ], + [ + "rules_python+", + "pypi__setuptools", + "rules_python++config+pypi__setuptools" + ], + [ + "rules_python+", + "pypi__tomli", + "rules_python++config+pypi__tomli" + ], + [ + "rules_python+", + "pypi__wheel", + "rules_python++config+pypi__wheel" + ], + [ + "rules_python+", + "pypi__zipp", + "rules_python++config+pypi__zipp" + ], + [ + "rules_python+", + "rules_cc", + "rules_cc+" + ], + [ + "rules_python+", + "rules_python_internal", + "rules_python++config+rules_python_internal" + ], + [ + "rules_python++config+rules_python_internal", + "rules_python", + "rules_python+" + ], + [ + "score_bazel_tools_cc+", + "bazel_tools_python", + "score_bazel_tools_python+" + ], + [ + "score_bazel_tools_cc+", + "score_bazel_tools_cc", + "score_bazel_tools_cc+" + ], + [ + "score_bazel_tools_python+", + "rules_python", + "rules_python+" + ] + ] + } + }, "@@score_rules_imagefs+//extensions:imagefs.bzl%imagefs": { "general": { "bzlTransitiveDigest": "6ZLANe53LXwcnne1ZrZm9GkJ9H5VdsCLSgSNHyUrqA4=", @@ -9910,6 +10068,85 @@ }, "recordedRepoMappingEntries": [] } + }, + "@@toolchains_llvm+//toolchain/extensions:llvm.bzl%llvm": { + "general": { + "bzlTransitiveDigest": "2nizkGuHTT5Rnm/m2ZKyN0gz6PG1uMRn/wIec1UMxaw=", + "usagesDigest": "Gtth39CdsnpUT5yLLTJT3RufqV5GtR3NGLNC0a6148E=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "llvm_toolchain_llvm": { + "repoRuleId": "@@toolchains_llvm+//toolchain:rules.bzl%llvm", + "attributes": { + "alternative_llvm_sources": [], + "auth_patterns": {}, + "distribution": "auto", + "exec_arch": "", + "exec_os": "", + "libclang_rt": {}, + "llvm_mirror": "", + "llvm_version": "15.0.2", + "llvm_versions": {}, + "netrc": "", + "sha256": {}, + "strip_prefix": {}, + "urls": {} + } + }, + "llvm_toolchain": { + "repoRuleId": "@@toolchains_llvm+//toolchain:rules.bzl%toolchain", + "attributes": { + "absolute_paths": false, + "archive_flags": {}, + "compile_flags": {}, + "conly_flags": {}, + "coverage_compile_flags": {}, + "coverage_link_flags": {}, + "cxx_builtin_include_directories": {}, + "cxx_flags": {}, + "cxx_standard": {}, + "dbg_compile_flags": {}, + "exec_arch": "", + "exec_os": "", + "extra_exec_compatible_with": {}, + "extra_target_compatible_with": {}, + "link_flags": {}, + "link_libs": {}, + "llvm_versions": { + "": "15.0.2" + }, + "opt_compile_flags": {}, + "opt_link_flags": {}, + "stdlib": { + "linux-x86_64": "stdc++" + }, + "target_settings": {}, + "unfiltered_compile_flags": {}, + "toolchain_roots": {}, + "sysroot": {} + } + } + }, + "recordedRepoMappingEntries": [ + [ + "toolchains_llvm+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "toolchains_llvm+", + "bazel_tools", + "bazel_tools" + ], + [ + "toolchains_llvm+", + "toolchains_llvm", + "toolchains_llvm+" + ] + ] + } } }, "facts": {} diff --git a/cr_checker_exclusion b/cr_checker_exclusion new file mode 100644 index 000000000..e69de29bb diff --git a/externals/acl/BUILD b/externals/acl/BUILD index acb12165f..becc38acf 100644 --- a/externals/acl/BUILD +++ b/externals/acl/BUILD @@ -1,3 +1,16 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + alias( name = "acl", actual = select({ diff --git a/externals/acl/acl.BUILD b/externals/acl/acl.BUILD index b695a6ac8..28c9f1e99 100644 --- a/externals/acl/acl.BUILD +++ b/externals/acl/acl.BUILD @@ -1,3 +1,16 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + cc_library( name = "acl", srcs = select({ diff --git a/externals/ipc_dropin/BUILD b/externals/ipc_dropin/BUILD index 2cfe80c9f..93fd90b37 100644 --- a/externals/ipc_dropin/BUILD +++ b/externals/ipc_dropin/BUILD @@ -1,3 +1,16 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + cc_library( name = "ipc_dropin_internal", hdrs = glob(["include/ipc_dropin/*.hpp"]), diff --git a/externals/ipc_dropin/include/ipc_dropin/ringbuffer.hpp b/externals/ipc_dropin/include/ipc_dropin/ringbuffer.hpp index a1d12c270..8bf13fc9d 100644 --- a/externals/ipc_dropin/include/ipc_dropin/ringbuffer.hpp +++ b/externals/ipc_dropin/include/ipc_dropin/ringbuffer.hpp @@ -1,3 +1,16 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + #ifndef IPC_DROPIN_RINGBUFFER_HPP_ #define IPC_DROPIN_RINGBUFFER_HPP_ diff --git a/externals/ipc_dropin/include/ipc_dropin/socket.hpp b/externals/ipc_dropin/include/ipc_dropin/socket.hpp index 2f12d982b..09ee0f1a7 100644 --- a/externals/ipc_dropin/include/ipc_dropin/socket.hpp +++ b/externals/ipc_dropin/include/ipc_dropin/socket.hpp @@ -1,3 +1,16 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + #ifndef IPC_DROPIN_SOCKET_HPP_ #define IPC_DROPIN_SOCKET_HPP_ diff --git a/patches/BUILD b/patches/BUILD new file mode 100644 index 000000000..42ef274e6 --- /dev/null +++ b/patches/BUILD @@ -0,0 +1,5 @@ +exports_files(["hedron_compile_commands_env_vars.patch"]) + +exports_files(["score_bazel_tools.patch"]) + +exports_files(["score_bazel_tools_python.patch"]) diff --git a/patches/hedron_compile_commands_env_vars.patch b/patches/hedron_compile_commands_env_vars.patch new file mode 100644 index 000000000..56b892ef5 --- /dev/null +++ b/patches/hedron_compile_commands_env_vars.patch @@ -0,0 +1,11 @@ +--- a/refresh.template.py ++++ b/refresh.template.py +@@ -1103,6 +1103,6 @@ def _get_cpp_command_for_files(compile_action): + Undo Bazel-isms and figures out which files clangd should apply the command to. + """ + # Condense aquery's environment variables into a dictionary, the format you might expect. +- compile_action.environmentVariables = {pair.key: pair.value for pair in getattr(compile_action, 'environmentVariables', [])} ++ compile_action.environmentVariables = {pair.key: getattr(pair, 'value', '') for pair in getattr(compile_action, 'environmentVariables', [])} + if 'PATH' not in compile_action.environmentVariables: # Bazel only adds if --incompatible_strict_action_env is passed--and otherwise inherits. + compile_action.environmentVariables['PATH'] = os.environ['PATH'] + diff --git a/patches/score_bazel_tools.patch b/patches/score_bazel_tools.patch new file mode 100644 index 000000000..92fc7db0d --- /dev/null +++ b/patches/score_bazel_tools.patch @@ -0,0 +1,6 @@ +--- MODULE.bazel ++++ MODULE.bazel +@@ -66,1 +66,0 @@ +- "3.8", +@@ -109,1 +108,0 @@ +- score_bazel_tools_cc_python_3_8 = "python_3_8", diff --git a/patches/score_bazel_tools_python.patch b/patches/score_bazel_tools_python.patch new file mode 100644 index 000000000..ee89dcdee --- /dev/null +++ b/patches/score_bazel_tools_python.patch @@ -0,0 +1,6 @@ +--- MODULE.bazel ++++ MODULE.bazel +@@ -53,1 +53,0 @@ +- "3.8", +@@ -90,1 +89,0 @@ +- bazel_tools_python_python_3_8 = "python_3_8", diff --git a/scripts/config_mapping/BUILD b/scripts/config_mapping/BUILD index 0ef907678..ea4b3a8a9 100644 --- a/scripts/config_mapping/BUILD +++ b/scripts/config_mapping/BUILD @@ -1,3 +1,16 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + load("@score_lifecycle_pip//:requirements.bzl", "requirement") exports_files([ diff --git a/scripts/config_mapping/config.bzl b/scripts/config_mapping/config.bzl index 60fe0fd32..0a07e26dc 100644 --- a/scripts/config_mapping/config.bzl +++ b/scripts/config_mapping/config.bzl @@ -1,3 +1,16 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + load("@rules_pkg//pkg:mappings.bzl", "pkg_files") load("@score_baselibs//score/flatbuffers/bazel:tools.bzl", "serialize_buffer") diff --git a/scripts/config_mapping/integration_tests.py b/scripts/config_mapping/integration_tests.py index c9aabdce7..b393a6ac1 100644 --- a/scripts/config_mapping/integration_tests.py +++ b/scripts/config_mapping/integration_tests.py @@ -1,4 +1,16 @@ #!/usr/bin/env python3 +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* import subprocess import shutil diff --git a/scripts/config_mapping/lifecycle_config.py b/scripts/config_mapping/lifecycle_config.py index 2346dbcb8..680ac4b1f 100644 --- a/scripts/config_mapping/lifecycle_config.py +++ b/scripts/config_mapping/lifecycle_config.py @@ -1,4 +1,16 @@ #!/usr/bin/env python3 +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* import argparse from copy import deepcopy diff --git a/scripts/config_mapping/tests/BUILD b/scripts/config_mapping/tests/BUILD index 9bffa7a74..9bf775d3c 100644 --- a/scripts/config_mapping/tests/BUILD +++ b/scripts/config_mapping/tests/BUILD @@ -1,3 +1,16 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + load("@score_lifecycle_pip//:requirements.bzl", "requirement") load("@score_tooling//:defs.bzl", "score_py_pytest") diff --git a/scripts/config_mapping/unit_tests.py b/scripts/config_mapping/unit_tests.py index 33635d2ec..4a9d592a3 100644 --- a/scripts/config_mapping/unit_tests.py +++ b/scripts/config_mapping/unit_tests.py @@ -1,4 +1,17 @@ #!/usr/bin/env python3 +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + from scripts.config_mapping.lifecycle_config import preprocess_defaults import json diff --git a/scripts/generate_cpp_compile_commands.sh b/scripts/generate_cpp_compile_commands.sh index bc88adb3e..9fcd796d6 100755 --- a/scripts/generate_cpp_compile_commands.sh +++ b/scripts/generate_cpp_compile_commands.sh @@ -1,3 +1,15 @@ -#!/bin/bash +#!/usr/bin/env bash +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* -bazel run @hedron_compile_commands//:refresh_all +bazel run //:generate_compile_commands -- --config=x86_64-linux diff --git a/scripts/generate_rust_analyzer_support.sh b/scripts/generate_rust_analyzer_support.sh index fa9b1ff41..57c51b70f 100755 --- a/scripts/generate_rust_analyzer_support.sh +++ b/scripts/generate_rust_analyzer_support.sh @@ -1,5 +1,16 @@ -#!/bin/bash - +#!/usr/bin/env bash +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* set -e # Manual targets are not take into account, must be set explicitly diff --git a/scripts/run_clang_tidy_precommit.py b/scripts/run_clang_tidy_precommit.py new file mode 100644 index 000000000..65a560169 --- /dev/null +++ b/scripts/run_clang_tidy_precommit.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +from __future__ import annotations + +import json +import shutil +import subprocess +import sys +import tempfile +from pathlib import Path + + +def run(cmd: list[str], cwd: Path) -> None: + subprocess.run(cmd, cwd=cwd, check=True) + + +def sanitize_compile_commands(input_path: Path, output_path: Path) -> None: + with input_path.open("r", encoding="utf-8") as f: + db = json.load(f) + + for entry in db: + args = entry.get("arguments") + if isinstance(args, list): + filtered: list[str] = [] + skip_next = False + for arg in args: + if skip_next: + skip_next = False + continue + if arg == "-z": + skip_next = True + continue + if arg.startswith("-z "): + continue + filtered.append(arg) + entry["arguments"] = filtered + + cmd = entry.get("command") + if isinstance(cmd, str): + entry["command"] = cmd.replace(" -z noexecstack", "") + + with output_path.open("w", encoding="utf-8") as f: + json.dump(db, f) + + +def main() -> int: + repo_root = Path(__file__).resolve().parent.parent + compile_db = repo_root / "compile_commands.json" + + if not compile_db.exists(): + run( + [ + "bazel", + "run", + "//:generate_compile_commands", + "--", + "--config=x86_64-linux", + ], + cwd=repo_root, + quiet=True, + ) + + tool = ( + repo_root + / "bazel-bin" + / "external" + / "toolchains_llvm++llvm+llvm_toolchain" + / "clang-tidy" + ) + if not (tool.exists() and os_access_executable(tool)): + run(["bazel", "build", "@llvm_toolchain//:clang-tidy"]) + + with tempfile.TemporaryDirectory() as tmp_dir: + tmp_compile_db = Path(tmp_dir) / "compile_commands.json" + sanitize_compile_commands(compile_db, tmp_compile_db) + + cmd = [str(tool), f"-p={tmp_dir}", *sys.argv[1:]] + completed = subprocess.run(cmd, cwd=repo_root) + return completed.returncode + + +def os_access_executable(path: Path) -> bool: + return path.exists() and bool(path.stat().st_mode & 0o111) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tests/integration/BUILD b/tests/integration/BUILD index cd0c9e27f..b82493d65 100644 --- a/tests/integration/BUILD +++ b/tests/integration/BUILD @@ -10,6 +10,8 @@ # # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* + +load("@rules_python//python:pip.bzl", "compile_pip_requirements") load("@score_lifecycle_pip//:requirements.bzl", "requirement") load("@score_tooling//python_basics:defs.bzl", "score_virtualenv") diff --git a/tests/integration/switch_run_target/common.hpp b/tests/integration/switch_run_target/common.hpp index e7ede7e86..0f5847e8d 100644 --- a/tests/integration/switch_run_target/common.hpp +++ b/tests/integration/switch_run_target/common.hpp @@ -1,3 +1,16 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + #ifndef SWITCH_RUN_TARGET_HEADER #define SWITCH_RUN_TARGET_HEADER From 6fd870b22b27d5b89ff6eef13d029cc99bf829c9 Mon Sep 17 00:00:00 2001 From: Paul Quiring Date: Fri, 17 Jul 2026 09:18:27 +0200 Subject: [PATCH 2/2] Use llvm clang-tidy clang-format --- .clang_format => .clang-format | 1 - .pre-commit-config.yaml | 8 +--- scripts/run_clang_format_precommit.sh | 22 ++++++++++ scripts/run_clang_tidy_precommit.py | 58 ++++++++++++++++++--------- 4 files changed, 64 insertions(+), 25 deletions(-) rename .clang_format => .clang-format (93%) create mode 100644 scripts/run_clang_format_precommit.sh diff --git a/.clang_format b/.clang-format similarity index 93% rename from .clang_format rename to .clang-format index 857de2800..1024fae82 100644 --- a/.clang_format +++ b/.clang-format @@ -1,4 +1,3 @@ ---- BasedOnStyle: Google ColumnLimit: 120 IndentWidth: 4 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 462883cb4..1184fd0a2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,16 +30,13 @@ repos: hooks: - id: clang-format name: clang-format - # Run the tool binary directly so pre-commit's staged relative paths work. - # If clang-format cannot be found, the toolchain folder name likely changed. - entry: bazel-bin/external/toolchains_llvm++llvm+llvm_toolchain/clang-format -i + entry: ./scripts/run_clang_format_precommit.sh language: system files: '\.(c|cc|cpp|h|hpp)$' # all relevant files are currently excluded the format is not # clarified yet, so we don't want to run clang-format on any files exclude: | (?x)^( - externals/| examples/| tests/| score/ @@ -48,14 +45,13 @@ repos: name: clang-tidy # Run through a wrapper that sanitizes unsupported linker flags in # compile_commands.json before invoking clang-tidy. - entry: ./scripts/run_clang_tidy_precommit.py + entry: python3 ./scripts/run_clang_tidy_precommit.py language: system files: '\.(c|cc|cpp|h|hpp)$' # all relevant files are currently excluded the checks are # not clarified yet, so we don't want to run clang-tidy on any files exclude: | (?x)^( - externals/| examples/| tests/| score/ diff --git a/scripts/run_clang_format_precommit.sh b/scripts/run_clang_format_precommit.sh new file mode 100644 index 000000000..ed21a44b1 --- /dev/null +++ b/scripts/run_clang_format_precommit.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +set -e + +clang_format_bin=$(bazel cquery @llvm_toolchain//:clang-format --output files 2>/dev/null) +if [ -f "$clang_format_bin" ]; then + "$clang_format_bin" -i "$@" +else + bazel build @llvm_toolchain//:clang-format + "$clang_format_bin" -i "$@" +fi diff --git a/scripts/run_clang_tidy_precommit.py b/scripts/run_clang_tidy_precommit.py index 65a560169..2009a1491 100644 --- a/scripts/run_clang_tidy_precommit.py +++ b/scripts/run_clang_tidy_precommit.py @@ -12,18 +12,40 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -from __future__ import annotations - import json -import shutil +import os import subprocess import sys import tempfile from pathlib import Path -def run(cmd: list[str], cwd: Path) -> None: - subprocess.run(cmd, cwd=cwd, check=True) +def run(cmd: list[str], cwd: Path, quiet: bool = False) -> str: + """Run a command and return its output.""" + result = subprocess.run(cmd, cwd=cwd, check=True, capture_output=True, text=True) + if not quiet: + if result.stdout: + sys.stdout.write(result.stdout) + if result.stderr: + sys.stderr.write(result.stderr) + return result.stdout + + +def resolve_tool_path(repo_root: Path) -> Path | None: + output = run( + ["bazel", "cquery", "@llvm_toolchain//:clang-tidy", "--output", "files"], + cwd=repo_root, + quiet=True, + ) + for line in output.splitlines(): + line = line.strip() + if "/clang-tidy" in line: + path = Path(line) + if not path.is_absolute(): + path = repo_root / path + if path.is_file() and os.access(path, os.X_OK): + return path + return None def sanitize_compile_commands(input_path: Path, output_path: Path) -> None: @@ -72,15 +94,19 @@ def main() -> int: quiet=True, ) - tool = ( - repo_root - / "bazel-bin" - / "external" - / "toolchains_llvm++llvm+llvm_toolchain" - / "clang-tidy" - ) - if not (tool.exists() and os_access_executable(tool)): - run(["bazel", "build", "@llvm_toolchain//:clang-tidy"]) + tool = resolve_tool_path(repo_root) + if tool is None: + run( + ["bazel", "build", "@llvm_toolchain//:clang-tidy"], + cwd=repo_root, + quiet=True, + ) + tool = resolve_tool_path(repo_root) + if tool is None: + raise RuntimeError( + "Could not resolve clang-tidy path from bazel cquery output " + "after building @llvm_toolchain//:clang-tidy" + ) with tempfile.TemporaryDirectory() as tmp_dir: tmp_compile_db = Path(tmp_dir) / "compile_commands.json" @@ -91,9 +117,5 @@ def main() -> int: return completed.returncode -def os_access_executable(path: Path) -> bool: - return path.exists() and bool(path.stat().st_mode & 0o111) - - if __name__ == "__main__": raise SystemExit(main())