xref: /aosp_15_r20/build/soong/docs/tidy.md (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1# Clang-Tidy Rules and Checks
2
3Android C/C++ source files can be checked by clang-tidy for issues like
4coding style, error-prone/performance patterns, and static flow analysis.
5See the official
6[clang-tidy document](https://clang.llvm.org/extra/clang-tidy)
7and list of
8[clang-tidy checks](https://clang.llvm.org/extra/clang-tidy/checks/list.html).
9
10## Global defaults for Android builds
11
12The simplest way to enable clang-tidy checks is
13to set environment variable `WITH_TIDY`.
14```
15$ WITH_TIDY=1 make
16```
17
18This will turn on the global default to run clang-tidy for every required
19C/C++ source file compilation. The global default clang-tidy checks
20do not include time-consuming static analyzer checks. To enable those
21checks, set the `CLANG_ANALYZER_CHECKS` variable.
22```
23$ WITH_TIDY=1 CLANG_ANALYZER_CHECKS=1 make
24```
25
26The default global clang-tidy checks and flags are defined in
27[build/soong/cc/config/tidy.go](https://android.googlesource.com/platform/build/soong/+/refs/heads/main/cc/config/tidy.go).
28
29
30## Module clang-tidy properties
31
32The global default can be overwritten by module properties in Android.bp.
33
34### `tidy`, `tidy_checks`, and `ALLOW_LOCAL_TIDY_TRUE`
35
36For example, in
37[system/bpf/Android.bp](https://android.googlesource.com/platform/system/bpf/+/refs/heads/main/Android.bp),
38clang-tidy is enabled explicitly and with a different check list:
39```
40cc_defaults {
41    name: "bpf_cc_defaults",
42    // snipped
43    tidy: true,
44    tidy_checks: [
45        "android-*",
46        "cert-*",
47        "-cert-err34-c",
48        "clang-analyzer-security*",
49        // Disabling due to many unavoidable warnings from POSIX API usage.
50        "-google-runtime-int",
51    ],
52}
53```
54That means in normal builds, even without `WITH_TIDY=1`,
55the modules that use `bpf_cc_defaults` _should_ run clang-tidy
56over C/C++ source files with the given `tidy_checks`.
57
58However since clang-tidy warnings and its runtime cost might
59not be wanted by all people, the default is to ignore the
60`tidy:true` property unless the environment variable
61`ALLOW_LOCAL_TIDY_TRUE` is set to true or 1.
62To run clang-tidy on all modules that should be tested with clang-tidy,
63`ALLOW_LOCAL_TIDY_TRUE` or `WITH_TIDY` should be set to true or 1.
64
65Note that `clang-analyzer-security*` is included in `tidy_checks`
66but not all `clang-analyzer-*` checks. Check `cert-err34-c` is
67disabled, although `cert-*` is selected.
68
69Some modules might want to disable clang-tidy even when
70environment variable `WITH_TIDY=1` is set.
71Examples can be found in
72[system/netd/tests/Android.bp](https://android.googlesource.com/platform/system/netd/+/refs/heads/main/tests/Android.bp)
73```
74cc_test {
75    name: "netd_integration_test",
76    // snipped
77    defaults: ["netd_defaults"],
78    tidy: false,  // cuts test build time by almost 1 minute
79```
80and in
81[bionic/tests/Android.bp](https://android.googlesource.com/platform/bionic/+/refs/heads/main/tests/Android.bp).
82```
83cc_test_library {
84    name: "fortify_disabled_for_tidy",
85    // snipped
86    srcs: ["clang_fortify_tests.cpp"],
87    tidy: false,
88}
89```
90
91Note that `tidy:false` always disables clang-tidy, no matter
92`ALLOW_LOCAL_TIDY_TRUE` is set or not.
93
94### `tidy_checks_as_errors`
95
96The global tidy checks are enabled as warnings.
97If a C/C++ module wants to be free of certain clang-tidy warnings,
98it can chose those checks to be treated as errors.
99For example
100[system/core/libsysutils/Android.bp](https://android.googlesource.com/platform/system/core/+/refs/heads/main/libsysutils/Android.bp)
101has enabled clang-tidy explicitly, selected its own tidy checks,
102and set three groups of tidy checks as errors:
103```
104cc_library {
105    name: "libsysutils",
106    // snipped
107    tidy: true,
108    tidy_checks: [
109        "-*",
110        "cert-*",
111        "clang-analyzer-security*",
112        "android-*",
113    ],
114    tidy_checks_as_errors: [
115        "cert-*",
116        "clang-analyzer-security*",
117        "android-*",
118    ],
119    // snipped
120}
121```
122
123### `tidy_flags` and `tidy_disabled_srcs`
124
125Extra clang-tidy flags can be passed with the `tidy_flags` property.
126
127Some Android modules use the `tidy_flags` to pass "-warnings-as-errors="
128to clang-tidy. This usage should now be replaced with the
129`tidy_checks_as_errors` property.
130
131Some other tidy flags examples are `-format-style=` and `-header-filter=`
132For example, in
133[art/odrefresh/Android.bp](https://android.googlesource.com/platform/art/+/refs/heads/main/odrefresh/Android.bp),
134we found
135```
136cc_defaults {
137    name: "odrefresh-defaults",
138    srcs: [
139        "odrefresh.cc",
140        "odr_common.cc",
141        "odr_compilation_log.cc",
142        "odr_fs_utils.cc",
143        "odr_metrics.cc",
144        "odr_metrics_record.cc",
145    ],
146    // snipped
147    generated_sources: [
148        "apex-info-list-tinyxml",
149        "art-apex-cache-info",
150        "art-odrefresh-operator-srcs",
151    ],
152    // snipped
153    tidy: true,
154    tidy_disabled_srcs: [":art-apex-cache-info"],
155    tidy_flags: [
156        "-format-style=file",
157        "-header-filter=(art/odrefresh/|system/apex/)",
158    ],
159}
160```
161That means all modules with the `odrefresh-defaults` will
162have clang-tidy enabled, but not for generated source
163files in `art-apex-cache-info`.
164The clang-tidy is called with extra flags to specify the
165format-style and header-filter.
166
167Note that the globally set default for header-filter is to
168include only the module directory. So, the default clang-tidy
169warnings for `art/odrefresh` modules will include source files
170under that directory. Now `odrefresh-defaults` is interested
171in seeing warnings from both `art/odrefresh/` and `system/apex/`
172and it redefines `-header-filter` in its `tidy_flags`.
173
174
175## Phony tidy-* targets
176
177### The tidy-*directory* targets
178
179Setting `WITH_TIDY=1` is easy to enable clang-tidy globally for any build.
180However, it adds extra compilation time.
181
182For developers focusing on just one directory, they only want to compile
183their files with clang-tidy and wish to build other Android components as
184fast as possible. Changing the `WITH_TIDY=1` variable setting is also expensive
185since the build.ninja file will be regenerated due to any such variable change.
186
187To manually select only some directories or modules to compile with clang-tidy,
188do not set the `WITH_TIDY=1` variable, but use the special `tidy-<directory>`
189phony target. For example, a person working on `system/libbase` can build
190Android quickly with
191```
192unset WITH_TIDY # Optional, not if you haven't set WITH_TIDY
193make droid tidy-system-libbase
194```
195
196For any directory `d1/d2/d3`, a phony target tidy-d1-d2-d3 is generated
197if there is any C/C++ source file under `d1/d2/d3`.
198
199Note that with `make droid tidy-system-libbase`, some C/C++ files
200that are not needed by the `droid` target will be passed to clang-tidy
201if they are under `system/libbase`. This is like a `checkbuild`
202under `system/libbase` to include all modules, but only C/C++
203files of those modules are compiled with clang-tidy.
204
205### The tidy-soong target
206
207A special `tidy-soong` target is defined to include all C/C++
208source files in *all* directories. This phony target is sometimes
209used to test if all source files compile with a new clang-tidy release.
210
211### The tidy-*_subset targets
212
213A *subset* of each tidy-* phony target is defined to reduce test time.
214Since any Android module, a C/C++ library or binary, can be built
215for many different *variants*, one C/C++ source file is usually
216compiled multiple times with different compilation flags.
217Many of such *variant* flags have little or no effect on clang-tidy
218checks. To reduce clang-tidy check time, a *subset* target like
219`tidy-soong_subset` or `tidy-system-libbase_subset` is generated
220to include only a subset, the first variant, of each module in
221the directory.
222
223Hence, for C/C++ source code quality, instead of a long
224"make checkbuild", we can use "make tidy-soong_subset".
225
226
227## Limit clang-tidy runtime
228
229Some Android modules have large files that take a long time to compile
230with clang-tidy, with or without the clang-analyzer checks.
231To limit clang-tidy time, an environment variable can be set as
232```base
233WITH_TIDY=1 TIDY_TIMEOUT=90 make
234```
235This 90-second limit is actually the default time limit
236in several Android continuous builds where `WITH_TIDY=1` and
237`CLANG_ANALYZER_CHECKS=1` are set.
238
239Similar to `tidy_disabled_srcs` a `tidy_timeout_srcs` list
240can be used to include all source files that took too much time to compile
241with clang-tidy. Files listed in `tidy_timeout_srcs` will not
242be compiled by clang-tidy when `TIDY_TIMEOUT` is defined.
243This can save global build time, when it is necessary to set some
244time limit globally to finish in an acceptable time.
245For developers who want to find all clang-tidy warnings and
246are willing to spend more time on all files in a project,
247they should not define `TIDY_TIMEOUT` and build only the wanted project directories.
248
249## Capabilities for Android.bp and Android.mk
250
251Some of the previously mentioned features are defined only
252for modules in Android.bp files, not for Android.mk modules yet.
253
254* The global `WITH_TIDY=1` variable will enable clang-tidy for all C/C++
255  modules in Android.bp or Android.mk files.
256
257* The global `TIDY_TIMEOUT` variable is recognized by Android prebuilt
258  clang-tidy, so it should work for any clang-tidy invocation.
259
260* The clang-tidy module level properties are defined for Android.bp modules.
261  For Android.mk modules, old `LOCAL_TIDY`, `LOCAL_TIDY_CHECKS`,
262  `LOCAL_TIDY_FLAGS` work similarly, but it would be better to convert
263  those modules to use Android.bp files.
264
265* The `tidy-*` phony targets are only generated for Android.bp modules.
266