# 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/master/cc/config/tidy.go). ## Module clang-tidy properties The global default can be overwritten by module properties in Android.bp. ### `tidy` and `tidy_checks` For example, in [system/bpf/Android.bp](https://android.googlesource.com/platform/system/bpf/+/refs/heads/master/Android.bp), clang-tidy is enabled explicitly and with a different check list: ``` cc_defaults { name: "bpf_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_defaults` will run clang-tidy over C/C++ source files with the given `tidy_checks`. 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/master/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/master/tests/Android.bp). ``` cc_test_library { name: "fortify_disabled_for_tidy", // snipped srcs: ["clang_fortify_tests.cpp"], tidy: false, } ``` ### `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/master/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/master/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-` 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.