Skip to content

Commit b6551c2

Browse files
authored
Add centralized clang-tidy infrastructure (#2)
* fix review comments: fix clang-tidy yaml and remove issue templates * Fix review comments: sanitizers.bazelrc bugs, restore lsan Rust suppression, remove dead clang_tidy.bazelrc, improve HeaderFilterRegex and docs * Remove sanitizer changes * fix review comments: update READMEs and drop defs.bzl thin wrapper
1 parent 6348b27 commit b6551c2

15 files changed

Lines changed: 384 additions & 26 deletions

File tree

.github/PULL_REQUEST_TEMPLATE/improvement.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
## Related ticket
1414

1515
> [!IMPORTANT]
16-
> Please replace `[ISSUE-NUMBER]` with the issue-number that tracks this bug fix. If there is no such
16+
> Please replace `[ISSUE-NUMBER]` with the issue-number that tracks this improvement. If there is no such
1717
> ticket yet, create one via [this issue template](../ISSUE_TEMPLATE/new?template=improvement.md).
1818
1919
closes [ISSUE-NUMBER] (improvement ticket)

MODULE.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ module(name = "score_cpp_policies")
1515

1616
bazel_dep(name = "bazel_skylib", version = "1.8.2")
1717
bazel_dep(name = "platforms", version = "0.0.10")
18-
bazel_dep(name = "rules_cc", version = "0.1.5")
19-
18+
bazel_dep(name = "rules_cc", version = "0.2.17")
19+
bazel_dep(name = "aspect_rules_lint", version = "2.5.0")

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# score_cpp_policies
22

3-
Centralized C++ quality tool policies for Eclipse S-CORE, providing sanitizer configurations reusable across all S-CORE modules (logging, communication, baselibs, etc.).
3+
Centralized C++ quality tool policies for Eclipse S-CORE, providing sanitizer
4+
configurations and clang-tidy integration reusable across all S-CORE modules
5+
(logging, communication, baselibs, etc.).
46

5-
Planned: clang-tidy, clang-format, code coverage policies.
7+
Planned: clang-format, code coverage policies.
68

79
## What This Provides
810

@@ -11,6 +13,8 @@ Planned: clang-tidy, clang-format, code coverage policies.
1113
- **`sanitizers/sanitizers.bazelrc`** — canonical config that consumers import or copy
1214
- **Suppression files** — per-sanitizer suppression lists for known false positives (GoogleTest, etc.)
1315
- **Constraint system**`target_compatible_with` settings for sanitizer-incompatible targets
16+
- **`clang_tidy/.clang-tidy`** — centralized default check set (conservative baseline, tailorable per module)
17+
- **`clang_tidy/clang_tidy.bazelrc`**`--config=clang-tidy` bazelrc config consumers can import
1418

1519
## Available Sanitizer Configurations
1620

@@ -27,7 +31,7 @@ Planned: clang-tidy, clang-format, code coverage policies.
2731
### Add Dependency
2832

2933
```python
30-
bazel_dep(name = "score_cpp_policies", version = "0.0.0")
34+
bazel_dep(name = "score_cpp_policies")
3135
```
3236

3337
### Configure Sanitizers
@@ -103,6 +107,7 @@ cd tests
103107

104108
bazel test --config=asan_ubsan_lsan //...
105109
bazel test --config=tsan //...
110+
bazel test --config=clang-tidy //...
106111
```
107112

108113
## Contributing

clang_tidy/.clang-tidy

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
---
15+
# Default clang-tidy configuration for S-CORE C++ modules.
16+
# NOTE: the set of enabled checks is yet subject to be tailored per module.
17+
Checks: >-
18+
-*,
19+
clang-analyzer-*,
20+
cert-*,
21+
cppcoreguidelines-*,
22+
bugprone-*,
23+
misc-*,
24+
performance-*,
25+
readability-*,
26+
modernize-*
27+
28+
# NOTE: WarningsAsErrors is yet subject to be expanded per module as compliance increases.
29+
WarningsAsErrors: >-
30+
clang-analyzer-*
31+
32+
# HeaderFilterRegex is intentionally absent from the central baseline.
33+
# Each consuming module must set this in their local .clang-tidy to match
34+
# their own source tree (e.g., HeaderFilterRegex: 'score/mw/').
35+
# Setting it here would either suppress all header analysis (empty string)
36+
# or generate noise from external dependency headers (broad regex).
37+
# LLVM's regex engine does not reliably support POSIX lookaheads, so
38+
# negative-lookahead patterns like (?!.*/external/) must not be used here.
39+
40+
FormatStyle: none
41+
42+
# NOTE: CheckOptions are yet subject to be provided for each enabled check per module.
43+
#CheckOptions:
44+
# none yet

clang_tidy/BUILD.bazel

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
exports_files(
15+
[
16+
".clang-tidy",
17+
"clang_tidy.bazelrc",
18+
"defs.bzl",
19+
],
20+
visibility = ["//visibility:public"],
21+
)

clang_tidy/README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Clang-Tidy
2+
3+
Centralized clang-tidy configuration for Eclipse S-CORE C++ modules.
4+
5+
## What This Provides
6+
7+
| File | Purpose |
8+
|------|---------|
9+
| `.clang-tidy` | Canonical S-CORE check set (conservative baseline, tailorable per module) |
10+
| `clang_tidy.bazelrc` | Importable Bazel flags that activate the `clang-tidy` test config |
11+
12+
This module ships **policy assets**, not API wrappers. Consumers wire up
13+
`lint_clang_tidy_aspect` / `lint_test` from `@aspect_rules_lint` directly —
14+
exactly the same pattern used by the `sanitizers` module.
15+
16+
## Setup (8 steps)
17+
18+
### 1 — Add Bazel dependencies
19+
20+
In your `MODULE.bazel`:
21+
22+
```python
23+
bazel_dep(name = "score_cpp_policies", version = "<version>")
24+
bazel_dep(name = "aspect_rules_lint", version = "2.5.0")
25+
bazel_dep(name = "toolchains_llvm", version = "1.7.0")
26+
```
27+
28+
Register an LLVM toolchain via the `llvm` extension (see `tests/MODULE.bazel` for a
29+
minimal example).
30+
31+
### 2 — Import `clang_tidy.bazelrc`
32+
33+
In your workspace `.bazelrc`:
34+
35+
```bazelrc
36+
import %workspace%/path/to/clang_tidy.bazelrc # if vendored locally
37+
# — or, once Bazel supports external-repo imports —
38+
# import %workspace%/../clang_tidy/clang_tidy.bazelrc
39+
```
40+
41+
> **Tip**: If your repo layout places `score_cpp_policies` as a sibling (as in the
42+
> `tests/` self-test workspace here), a relative `import` works. Otherwise vendor
43+
> the three lines from `clang_tidy.bazelrc` into your own `.bazelrc`.
44+
45+
### 3 — Create `tools/lint/BUILD.bazel`
46+
47+
```python
48+
# tools/lint/BUILD.bazel (empty package marker is sufficient)
49+
```
50+
51+
### 4 — Create `tools/lint/linters.bzl`
52+
53+
```python
54+
load("@aspect_rules_lint//lint:clang_tidy.bzl", "lint_clang_tidy_aspect")
55+
load("@aspect_rules_lint//lint:lint_test.bzl", "lint_test")
56+
57+
clang_tidy_aspect = lint_clang_tidy_aspect(
58+
binary = Label("@llvm_toolchain//:clang-tidy"),
59+
configs = [
60+
Label("@score_cpp_policies//clang_tidy:.clang-tidy"), # central baseline
61+
Label("//:.clang-tidy"), # local overrides (optional)
62+
],
63+
lint_target_headers = True,
64+
angle_includes_are_system = True,
65+
)
66+
67+
clang_tidy_test = lint_test(aspect = clang_tidy_aspect)
68+
```
69+
70+
If you do not need per-module overrides, omit the `Label("//:.clang-tidy")` entry and
71+
skip step 5.
72+
73+
### 5 — (Optional) Add a local `.clang-tidy` override
74+
75+
Place a `.clang-tidy` at your repo root to extend or tighten the central check set.
76+
Use [`@score_cpp_policies//clang_tidy:.clang-tidy`](.clang-tidy) as the starting point.
77+
78+
> **Advisory checks**: Checks in the `cppcoreguidelines-*` and `modernize-*` families are
79+
> advisory (warnings only). Only `clang-analyzer-*` is `WarningsAsErrors` by default.
80+
> Module owners should tighten `WarningsAsErrors` incrementally as compliance improves.
81+
82+
### 6 — Expose `clang_tidy_test` in a `BUILD` file
83+
84+
```python
85+
load("//tools/lint:linters.bzl", "clang_tidy_test")
86+
87+
clang_tidy_test(
88+
name = "clang_tidy",
89+
srcs = ["//..."], # or a more targeted glob
90+
)
91+
```
92+
93+
### 7 — Run
94+
95+
```bash
96+
bazel test --config=clang-tidy //...
97+
```
98+
99+
Reports are written to `bazel-out/.../rules_lint_report/` as text files next to each
100+
linted target.
101+
102+
### 8 — CI integration
103+
104+
Add a workflow job that runs:
105+
106+
```bash
107+
bazel test --config=clang-tidy //...
108+
```

clang_tidy/clang_tidy.bazelrc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
test:clang-tidy --aspects=//tools/lint:linters.bzl%clang_tidy_aspect
15+
test:clang-tidy --output_groups=+rules_lint_report
16+
test:clang-tidy --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux

clang_tidy/defs.bzl

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
"""Public API for the S-CORE centralized clang-tidy policy.
15+
16+
Consumers load make_clang_tidy_aspect and make_clang_tidy_test from this file
17+
instead of calling aspect_rules_lint directly. This guarantees:
18+
19+
1. The S-CORE baseline .clang-tidy is always the first config applied.
20+
2. SCORE-specific aspect defaults (lint_target_headers, angle_includes_are_system)
21+
are pre-wired without requiring each consumer to rediscover them.
22+
3. When aspect_rules_lint changes its API, only this file needs updating;
23+
all consumers get the fix automatically on the next score_cpp_policies bump.
24+
"""
25+
26+
load("@aspect_rules_lint//lint:clang_tidy.bzl", "lint_clang_tidy_aspect")
27+
load("@aspect_rules_lint//lint:lint_test.bzl", "lint_test")
28+
29+
_BASELINE_CONFIG = Label("@score_cpp_policies//clang_tidy:.clang-tidy")
30+
31+
def make_clang_tidy_aspect(
32+
binary,
33+
local_configs = None,
34+
lint_target_headers = True,
35+
angle_includes_are_system = True):
36+
"""Creates a clang-tidy aspect pre-wired with the S-CORE baseline config.
37+
38+
The S-CORE baseline is always prepended to the config list. local_configs
39+
are applied on top and may only tighten checks or add module-specific
40+
suppressions — they cannot remove the baseline.
41+
42+
Args:
43+
binary: Label of the clang-tidy binary. Typically
44+
Label("@llvm_toolchain//:clang-tidy").
45+
local_configs: Optional list of Labels for module-specific .clang-tidy
46+
overrides, applied AFTER the S-CORE baseline.
47+
lint_target_headers: Whether to also analyze headers of each target.
48+
Default True. Set False to reduce CI time on very
49+
large build graphs.
50+
angle_includes_are_system: Whether <...> includes are treated as system
51+
headers (suppresses warnings from them).
52+
Default True.
53+
54+
Returns:
55+
A configured clang-tidy lint aspect.
56+
"""
57+
return lint_clang_tidy_aspect(
58+
binary = binary,
59+
configs = [_BASELINE_CONFIG] + (local_configs or []),
60+
lint_target_headers = lint_target_headers,
61+
angle_includes_are_system = angle_includes_are_system,
62+
)
63+
64+
# Re-exported for single-import convenience: consumers only need one load().
65+
make_clang_tidy_test = lint_test

sanitizers/features/BUILD.bazel

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ cc_args(
2727

2828
cc_feature(
2929
name = "debug_symbols",
30-
feature_name = "debug_symbols",
3130
args = [":debug_symbols_args"],
31+
feature_name = "debug_symbols",
3232
visibility = ["//visibility:public"],
3333
)
3434

@@ -61,11 +61,11 @@ cc_args(
6161

6262
cc_feature(
6363
name = "asan_ubsan_lsan",
64-
feature_name = "score_asan_ubsan_lsan",
6564
args = [
6665
":asan_ubsan_lsan_compile_args",
6766
":asan_ubsan_lsan_link_args",
6867
],
68+
feature_name = "score_asan_ubsan_lsan",
6969
implies = ["debug_symbols"],
7070
mutually_exclusive = [":sanitizer"],
7171
visibility = ["//visibility:public"],
@@ -99,11 +99,11 @@ cc_args(
9999

100100
cc_feature(
101101
name = "tsan",
102-
feature_name = "score_tsan",
103102
args = [
104103
":tsan_compile_args",
105104
":tsan_link_args",
106105
],
106+
feature_name = "score_tsan",
107107
implies = ["debug_symbols"],
108108
mutually_exclusive = [":sanitizer"],
109109
visibility = ["//visibility:public"],
@@ -122,11 +122,11 @@ cc_args(
122122

123123
cc_feature(
124124
name = "asan_ubsan_lsan_gcc",
125-
feature_name = "score_asan_ubsan_lsan",
126125
args = [
127126
":asan_ubsan_lsan_compile_args",
128127
":asan_ubsan_lsan_link_args_gcc",
129128
],
129+
feature_name = "score_asan_ubsan_lsan",
130130
implies = ["debug_symbols"],
131131
mutually_exclusive = [":sanitizer"],
132132
visibility = ["//visibility:public"],
@@ -141,11 +141,11 @@ cc_args(
141141

142142
cc_feature(
143143
name = "tsan_gcc",
144-
feature_name = "score_tsan",
145144
args = [
146145
":tsan_compile_args",
147146
":tsan_link_args_gcc",
148147
],
148+
feature_name = "score_tsan",
149149
implies = ["debug_symbols"],
150150
mutually_exclusive = [":sanitizer"],
151151
visibility = ["//visibility:public"],

tests/.bazelrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
# SPDX-License-Identifier: Apache-2.0
1212
# *******************************************************************************
1313

14-
# Import centralized sanitizer configurations
1514
import %workspace%/../sanitizers/sanitizers.bazelrc
1615

16+
import %workspace%/../clang_tidy/clang_tidy.bazelrc
17+
1718
common --registry=https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/
1819
common --registry=https://bcr.bazel.build
1920

20-
# Use LLVM toolchain for sanitizer configs (same as consuming modules)
2121
build:asan_ubsan_lsan --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux
2222
build:tsan --extra_toolchains=@llvm_toolchain//:cc-toolchain-x86_64-linux

0 commit comments

Comments
 (0)