1b1994897Sopenharmony_ci# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 2b1994897Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 3b1994897Sopenharmony_ci# you may not use this file except in compliance with the License. 4b1994897Sopenharmony_ci# You may obtain a copy of the License at 5b1994897Sopenharmony_ci# 6b1994897Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 7b1994897Sopenharmony_ci# 8b1994897Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 9b1994897Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 10b1994897Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11b1994897Sopenharmony_ci# See the License for the specific language governing permissions and 12b1994897Sopenharmony_ci# limitations under the License. 13b1994897Sopenharmony_ci 14b1994897Sopenharmony_cioption(PANDA_ENABLE_CLANG_TIDY "Enable clang-tidy checks during compilation" true) 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci# There seems to be a bug in either clang-tidy or CMake: 17b1994897Sopenharmony_ci# When clang/gcc is used for cross-compilation, it is ran on host and use defines and options for host 18b1994897Sopenharmony_ci# For example for arm32 cross-compilation Clang-Tidy: 19b1994897Sopenharmony_ci# - don't know about -march=armv7-a 20b1994897Sopenharmony_ci# - believes that size of pointer is 64 instead of 32 for aarch32 21b1994897Sopenharmony_ci# TODO: Retry once we upgrade the checker. 22b1994897Sopenharmony_ciif(CMAKE_CROSSCOMPILING AND PANDA_TARGET_ARM32) 23b1994897Sopenharmony_ci set(PANDA_ENABLE_CLANG_TIDY false) 24b1994897Sopenharmony_ciendif() 25b1994897Sopenharmony_ci 26b1994897Sopenharmony_ci# TODO (runtime): Remove this when enable tidy on qemu builds. 27b1994897Sopenharmony_ciif(CMAKE_CROSSCOMPILING) 28b1994897Sopenharmony_ci set(PANDA_ENABLE_CLANG_TIDY false) 29b1994897Sopenharmony_ciendif() 30b1994897Sopenharmony_ci 31b1994897Sopenharmony_ciif(PANDA_TARGET_MACOS) 32b1994897Sopenharmony_ci set(PANDA_ENABLE_CLANG_TIDY false) 33b1994897Sopenharmony_ciendif() 34b1994897Sopenharmony_ci 35b1994897Sopenharmony_ciif(PANDA_ENABLE_CLANG_TIDY) 36b1994897Sopenharmony_ci # Currently we fix a certain version of clang-tidy to avoid unstable linting, 37b1994897Sopenharmony_ci # which may occur if different versions of the tools are used by developers. 38b1994897Sopenharmony_ci set(panda_clang_tidy "clang-tidy-9") 39b1994897Sopenharmony_ci 40b1994897Sopenharmony_ci # Require clang-tidy 41b1994897Sopenharmony_ci find_program( 42b1994897Sopenharmony_ci CLANG_TIDY 43b1994897Sopenharmony_ci NAMES ${panda_clang_tidy} 44b1994897Sopenharmony_ci DOC "Path to clang-tidy executable") 45b1994897Sopenharmony_ci if(NOT CLANG_TIDY) 46b1994897Sopenharmony_ci message(FATAL_ERROR "clang-tidy not found, but requested for build. Use -DPANDA_ENABLE_CLANG_TIDY=false to suppress.") 47b1994897Sopenharmony_ci endif() 48b1994897Sopenharmony_ci 49b1994897Sopenharmony_ci unset(panda_clang_tidy) 50b1994897Sopenharmony_ci 51b1994897Sopenharmony_ci message(STATUS "clang-tidy found: ${CLANG_TIDY}") 52b1994897Sopenharmony_ci # NB! Even if config is malformed, clang-tidy -dump-config returns 0 on failure. 53b1994897Sopenharmony_ci # Hence we check for ERROR_VARIABLE instead of RESULT_VARIABLE. 54b1994897Sopenharmony_ci execute_process( 55b1994897Sopenharmony_ci COMMAND ${CLANG_TIDY} -dump-config 56b1994897Sopenharmony_ci WORKING_DIRECTORY ${PANDA_ROOT} 57b1994897Sopenharmony_ci ERROR_VARIABLE dump_config_stderr) 58b1994897Sopenharmony_ci if (dump_config_stderr AND NOT "${dump_config_stderr}" STREQUAL "") 59b1994897Sopenharmony_ci message(FATAL_ERROR "${dump_config_stderr}") 60b1994897Sopenharmony_ci endif() 61b1994897Sopenharmony_ci # See https://gitlab.kitware.com/cmake/cmake/issues/18926. 62b1994897Sopenharmony_ci # Create a preprocessor definition that depends on .clang-tidy content so 63b1994897Sopenharmony_ci # the compile command will change when .clang-tidy changes. This ensures 64b1994897Sopenharmony_ci # that a subsequent build re-runs clang-tidy on all sources even if they 65b1994897Sopenharmony_ci # do not otherwise need to be recompiled. Nothing actually uses this 66b1994897Sopenharmony_ci # definition. We add it to targets on which we run clang-tidy just to 67b1994897Sopenharmony_ci # get the build dependency on the .clang-tidy file. 68b1994897Sopenharmony_ci file(SHA1 ${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy clang_tidy_sha1) 69b1994897Sopenharmony_ci set(CLANG_TIDY_DEFINITIONS "CLANG_TIDY_SHA1=${clang_tidy_sha1}") 70b1994897Sopenharmony_ci unset(clang_tidy_sha1) 71b1994897Sopenharmony_ci configure_file(${PANDA_ROOT}/.clang-tidy ${PANDA_BINARY_ROOT}/.clang-tidy COPYONLY) 72b1994897Sopenharmony_ciendif() 73b1994897Sopenharmony_ci 74b1994897Sopenharmony_ci# Add a target to clang-tidy checks. 75b1994897Sopenharmony_ci# 76b1994897Sopenharmony_ci# Example usage: 77b1994897Sopenharmony_ci# 78b1994897Sopenharmony_ci# panda_add_to_clang_tidy(TARGET target_name 79b1994897Sopenharmony_ci# CHECKS 80b1994897Sopenharmony_ci# "-check-to-be-disabled" 81b1994897Sopenharmony_ci# "-glob-to-be-disabled-*" 82b1994897Sopenharmony_ci# "check-to-be-enabled" 83b1994897Sopenharmony_ci# "glob-to-be-enabled-*" 84b1994897Sopenharmony_ci# ) 85b1994897Sopenharmony_ci# 86b1994897Sopenharmony_ci# This function makes target_name to be co-compiled with clang-tidy. 87b1994897Sopenharmony_ci# The list of CHECKS allows to pass per-target checks in additions to 88b1994897Sopenharmony_ci# global ones (see below). CHECKS follow clang-tidy syntax of checks. 89b1994897Sopenharmony_ci# By default all checks are enabled globally, so the most reasonable use 90b1994897Sopenharmony_ci# case for CHECKS is to pass checks to be suppressed. 91b1994897Sopenharmony_ci 92b1994897Sopenharmony_ci# NB! Important caveats: 93b1994897Sopenharmony_ci# * We use permissive policy for checks, i.e. everything is enabled by default, 94b1994897Sopenharmony_ci# then exceptions are suppressed explicitly. 95b1994897Sopenharmony_ci# * We maintain the list of global exceptions in this function (not in .clang-tidy) 96b1994897Sopenharmony_ci# because of its syntax limitations (in particular, all checks should be passed 97b1994897Sopenharmony_ci# as a single string in YAML, which is not readable). 98b1994897Sopenharmony_ci# * -header-filter is set to check only headers of the target_name. It is supposed 99b1994897Sopenharmony_ci# that each components is responsible for QA'ing only its code base. 100b1994897Sopenharmony_cifunction(panda_add_to_clang_tidy) 101b1994897Sopenharmony_ci if(NOT PANDA_ENABLE_CLANG_TIDY) 102b1994897Sopenharmony_ci return() 103b1994897Sopenharmony_ci endif() 104b1994897Sopenharmony_ci 105b1994897Sopenharmony_ci set(prefix ARG) 106b1994897Sopenharmony_ci set(noValues) 107b1994897Sopenharmony_ci set(singleValues TARGET) 108b1994897Sopenharmony_ci set(multiValues CHECKS) 109b1994897Sopenharmony_ci 110b1994897Sopenharmony_ci cmake_parse_arguments(${prefix} 111b1994897Sopenharmony_ci "${noValues}" 112b1994897Sopenharmony_ci "${singleValues}" 113b1994897Sopenharmony_ci "${multiValues}" 114b1994897Sopenharmony_ci ${ARGN}) 115b1994897Sopenharmony_ci 116b1994897Sopenharmony_ci set(clang_tidy_params 117b1994897Sopenharmony_ci "${CLANG_TIDY}" 118b1994897Sopenharmony_ci "-config=" 119b1994897Sopenharmony_ci "-format-style=file" 120b1994897Sopenharmony_ci #"-header-filter='^(${CMAKE_CURRENT_SOURCE_DIR}|${CMAKE_CURRENT_BINARY_DIR}).*'" 121b1994897Sopenharmony_ci "-p='${PANDA_BINARY_ROOT}'" 122b1994897Sopenharmony_ci ) 123b1994897Sopenharmony_ci 124b1994897Sopenharmony_ci set(clang_tidy_default_exceptions 125b1994897Sopenharmony_ci # aliases for other checks(here full list: https://clang.llvm.org/extra/clang-tidy/checks/list.html): 126b1994897Sopenharmony_ci "-hicpp-braces-around-statements" # alias for readability-braces-around-statements 127b1994897Sopenharmony_ci "-google-readability-braces-around-statements" # alias for readability-braces-around-statements 128b1994897Sopenharmony_ci "-google-readability-function-size" # alias for readability-function-size 129b1994897Sopenharmony_ci "-hicpp-explicit-conversions" # alias for google-explicit-constructor 130b1994897Sopenharmony_ci "-hicpp-function-size" # alias for readability-function-size 131b1994897Sopenharmony_ci "-hicpp-no-array-decay" # alias for cppcoreguidelines-pro-bounds-array-to-pointer-decay 132b1994897Sopenharmony_ci "-hicpp-avoid-c-arrays" # alias for modernize-avoid-c-arrays 133b1994897Sopenharmony_ci "-cppcoreguidelines-avoid-c-arrays" # alias for modernize-avoid-c-arrays 134b1994897Sopenharmony_ci "-cppcoreguidelines-avoid-magic-numbers" # alias for readability-magic-numbers 135b1994897Sopenharmony_ci "-cppcoreguidelines-non-private-member-variables-in-classes" # alias for misc-non-private-member-variables-in-classes 136b1994897Sopenharmony_ci "-cert-dcl03-c" # alias for misc-static-assert 137b1994897Sopenharmony_ci "-hicpp-static-assert" # alias for misc-static-assert 138b1994897Sopenharmony_ci "-hicpp-no-malloc" # alias for cppcoreguidelines-no-malloc 139b1994897Sopenharmony_ci "-hicpp-vararg" # alias for cppcoreguidelines-pro-type-vararg 140b1994897Sopenharmony_ci "-hicpp-member-init" # alias for cppcoreguidelines-pro-type-member-init 141b1994897Sopenharmony_ci "-hicpp-move-const-arg" # alias for performance-move-const-arg 142b1994897Sopenharmony_ci "-cert-oop54-cpp" # alias for bugprone-unhandled-self-assignment 143b1994897Sopenharmony_ci # explicitly disabled checks 144b1994897Sopenharmony_ci "-bugprone-macro-parentheses" # disabled because it is hard to write macros with types with it 145b1994897Sopenharmony_ci "-llvm-header-guard" # disabled because of incorrect root prefix 146b1994897Sopenharmony_ci "-llvm-include-order" # disabled because conflicts with the clang-format 147b1994897Sopenharmony_ci "-readability-identifier-naming" # disabled because we will use little-hump-style 148b1994897Sopenharmony_ci "-google-runtime-references" # disabled to use non-const references 149b1994897Sopenharmony_ci "-fuchsia-trailing-return" # disabled because we have a lot of false positives and it is stylistic check 150b1994897Sopenharmony_ci "-fuchsia-default-arguments-calls" # disabled because we use functions with default arguments a lot 151b1994897Sopenharmony_ci "-fuchsia-default-arguments-declarations" # disabled because we use functions with default arguments a lot 152b1994897Sopenharmony_ci "-modernize-use-trailing-return-type" # disabled as a stylistic check 153b1994897Sopenharmony_ci "-clang-analyzer-optin.cplusplus.UninitializedObject" # disabled due to instability on clang-9 and clang-10 154b1994897Sopenharmony_ci "-readability-static-accessed-through-instance" # TODO(knazarov) fix all occurences 155b1994897Sopenharmony_ci "-readability-convert-member-functions-to-static" # TODO(knazarov) fix all occurences 156b1994897Sopenharmony_ci "-bugprone-sizeof-expression" # TODO(knazarov) fix all occurences 157b1994897Sopenharmony_ci "-bugprone-branch-clone" # TODO(knazarov) fix all occurences 158b1994897Sopenharmony_ci # TODOs 159b1994897Sopenharmony_ci "-cppcoreguidelines-owning-memory" # TODO(dtrubenkov): look if we want to use GSL or gsl-lite 160b1994897Sopenharmony_ci "-cppcoreguidelines-pro-bounds-array-to-pointer-decay" # TODO(dtrubenkov): look into issue with ASSERT 161b1994897Sopenharmony_ci "-cppcoreguidelines-pro-bounds-constant-array-index" # TODO(dtrubenkov): look if we want to use GSL or gsl-lite 162b1994897Sopenharmony_ci "-cppcoreguidelines-pro-type-const-cast" # TODO(dtrubenkov): consider to remove from global list 163b1994897Sopenharmony_ci "-cppcoreguidelines-pro-type-reinterpret-cast" # TODO(dtrubenkov): consider to remove from global list 164b1994897Sopenharmony_ci "-cppcoreguidelines-pro-type-static-cast-downcast" # TODO(dtrubenkov): look into it 165b1994897Sopenharmony_ci "-fuchsia-default-arguments" # TODO(dtrubenkov): look into it 166b1994897Sopenharmony_ci "-fuchsia-overloaded-operator" # TODO(dtrubenkov): consider to remove from global list 167b1994897Sopenharmony_ci "-modernize-use-nodiscard" # TODO(dtrubenkov): look into it 168b1994897Sopenharmony_ci "-cert-dcl50-cpp" # ailas for cppcoreguidelines-pro-type-vararg 169b1994897Sopenharmony_ci # candidates for removal: 170b1994897Sopenharmony_ci "-hicpp-noexcept-move" # For some reason become failed in DEFAULT_MOVE_SEMANTIC 171b1994897Sopenharmony_ci "-performance-noexcept-move-constructor" # Same as above 172b1994897Sopenharmony_ci ) 173b1994897Sopenharmony_ci # NB! Replace with list(JOIN ...) after switching to CMake 3.12+ 174b1994897Sopenharmony_ci string(REPLACE ";" "," default_exceptions "${clang_tidy_default_exceptions}") 175b1994897Sopenharmony_ci 176b1994897Sopenharmony_ci set(clang_tidy_checks "-checks=*,${default_exceptions}") 177b1994897Sopenharmony_ci 178b1994897Sopenharmony_ci if(DEFINED ARG_CHECKS) 179b1994897Sopenharmony_ci # NB! Replace with list(JOIN ...) after switching to CMake 3.12+ 180b1994897Sopenharmony_ci string(REPLACE ";" "," custom_checks "${ARG_CHECKS}") 181b1994897Sopenharmony_ci set(clang_tidy_checks "${clang_tidy_checks},${custom_checks}") 182b1994897Sopenharmony_ci endif() 183b1994897Sopenharmony_ci 184b1994897Sopenharmony_ci list(APPEND clang_tidy_params "${clang_tidy_checks}") 185b1994897Sopenharmony_ci 186b1994897Sopenharmony_ci set_target_properties(${ARG_TARGET} PROPERTIES CXX_CLANG_TIDY "${clang_tidy_params}") 187b1994897Sopenharmony_ciendfunction() 188