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