diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -127,11 +127,11 @@ During submission of patches, arcanist will automatically run `arc lint` to enforce Bitcoin ABC code formatting standards, and often suggests changes. If code formatting tools do not install automatically on your system, you -will have to install clang-format-8, autopep8, flake8, phpcs and shellcheck. +will have to install clang-format-8, clang-tidy (version >=8), autopep8, flake8, phpcs and shellcheck. -To install clang-format-8 on Ubuntu (>= 18.04+updates) or Debian (>= 10): +To install clang-format-8 and clang-format on Ubuntu (>= 18.04+updates) or Debian (>= 10): ``` -sudo apt-get install clang-format-8 +sudo apt-get install clang-format-8 clang-tidy-8 ``` To install clang-format-8 on OSX (requires npm): @@ -139,6 +139,11 @@ npm install -g clang-format@1.2.4 ``` +To install clang-tidy on OSX (requires Xcode): +``` +brew install llvm +``` + If not available in the distribution, clang-format-8 can be installed from https://releases.llvm.org/download.html or https://apt.llvm.org diff --git a/cmake/modules/ClangTidy.cmake b/cmake/modules/ClangTidy.cmake new file mode 100644 --- /dev/null +++ b/cmake/modules/ClangTidy.cmake @@ -0,0 +1,52 @@ +option(ENABLE_CLANG_TIDY "Enable clang-tidy checks" ON) + +if(ENABLE_CLANG_TIDY AND NOT CLANG_TIDY_BIN) + include(DoOrFail) + find_program_or_fail(CLANG_TIDY_BIN clang-tidy clang-tidy-8 clang-tidy-9 clang-tidy-10) + + # TODO check the version + execute_process( + COMMAND "${CLANG_TIDY_BIN}" -version + RESULT_VARIABLE CLANG_TIDY_VERSION_RESULT + OUTPUT_VARIABLE CLANG_TIDY_VERSION_OUTPUT + ) + + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CLANG_TIDY_VERSION "${CLANG_TIDY_VERSION_OUTPUT}") + if("${CLANG_TIDY_VERSION}" VERSION_LESS "8.0.0") + message(FATAL_ERROR "clang-tidy version >= 8 is required") + endif() + + message(STATUS "Using clang-tidy: ${CLANG_TIDY_BIN} (version ${CLANG_TIDY_VERSION})") + + # This is useful to run clang-tidy manually: + # clang-tidy <file.cpp> -checks=<whatever> -p compile_commands.json + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +endif() + +set(CLANG_TIDY_ARGS + "${CLANG_TIDY_BIN}" + -checks=-*,readability-braces-around-statements + -fix + -format-style=file +) + +function(_add_clang_tidy_checks_for_language LANGUAGE) + if(ENABLE_CLANG_TIDY) + foreach(_target ${ARGN}) + set_property(TARGET ${_target} PROPERTY "${LANGUAGE}_CLANG_TIDY" ${CLANG_TIDY_ARGS}) + endforeach() + endif() +endfunction() + +macro(add_c_clang_tidy_checks) + _add_clang_tidy_checks_for_language(C ${ARGN}) +endmacro() + +macro(add_cxx_clang_tidy_checks) + _add_clang_tidy_checks_for_language(CXX ${ARGN}) +endmacro() + +macro(add_clang_tidy_checks) + add_c_clang_tidy_checks(${ARGN}) + add_cxx_clang_tidy_checks(${ARGN}) +endmacro() diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -129,6 +129,7 @@ -DBUILD_BITCOIN_TX=OFF \ -DBUILD_BITCOIN_QT=OFF \ -DBUILD_LIBBITCOINCONSENSUS=OFF \ + -DENABLE_CLANG_TIDY=OFF \ -DENABLE_QRCODE=OFF \ -DENABLE_UPNP=OFF @@ -157,6 +158,7 @@ cmake -GNinja .. \ -DCMAKE_TOOLCHAIN_FILE=${SOURCEDIR}/cmake/platforms/${CMAKE_TOOLCHAIN_FILE[${i}]} \ -DCLIENT_VERSION_IS_RELEASE=ON \ + -DENABLE_CLANG_TIDY=OFF \ -DENABLE_REDUCE_EXPORTS=ON \ -DENABLE_STATIC_LIBSTDCXX=ON \ -DENABLE_GLIBC_BACK_COMPAT=ON \ diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -128,6 +128,7 @@ -DBUILD_BITCOIN_TX=OFF \ -DBUILD_BITCOIN_QT=OFF \ -DBUILD_LIBBITCOINCONSENSUS=OFF \ + -DENABLE_CLANG_TIDY=OFF \ -DENABLE_QRCODE=OFF \ -DENABLE_UPNP=OFF ninja package_source @@ -156,6 +157,7 @@ cmake -GNinja .. \ -DCMAKE_TOOLCHAIN_FILE=${SOURCEDIR}/cmake/platforms/${CMAKE_TOOLCHAIN_FILE[${i}]} \ -DCLIENT_VERSION_IS_RELEASE=ON \ + -DENABLE_CLANG_TIDY=OFF \ -DENABLE_REDUCE_EXPORTS=ON \ -DCMAKE_INSTALL_PREFIX=${INSTALLPATH} \ -DCCACHE=OFF \ diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -143,6 +143,7 @@ -DBUILD_BITCOIN_TX=OFF \ -DBUILD_BITCOIN_QT=OFF \ -DBUILD_LIBBITCOINCONSENSUS=OFF \ + -DENABLE_CLANG_TIDY=OFF \ -DENABLE_QRCODE=OFF \ -DENABLE_UPNP=OFF @@ -179,6 +180,7 @@ cmake -GNinja .. \ -DCMAKE_TOOLCHAIN_FILE=${SOURCEDIR}/cmake/platforms/${CMAKE_TOOLCHAIN_FILE[${i}]} \ -DCLIENT_VERSION_IS_RELEASE=ON \ + -DENABLE_CLANG_TIDY=OFF \ -DENABLE_REDUCE_EXPORTS=ON \ -DBUILD_BITCOIN_SEEDER=OFF \ -DCPACK_STRIP_FILES=ON \ diff --git a/contrib/teamcity/build_cmake.sh b/contrib/teamcity/build_cmake.sh --- a/contrib/teamcity/build_cmake.sh +++ b/contrib/teamcity/build_cmake.sh @@ -14,7 +14,7 @@ git clean -xffd read -a CMAKE_FLAGS <<< "${CMAKE_FLAGS}" -cmake -GNinja .. "${CMAKE_FLAGS[@]}" +cmake -GNinja .. -DENABLE_CLANG_TIDY=OFF "${CMAKE_FLAGS[@]}" # Run build ninja diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,7 @@ "-DBUILD_BITCOIN_ZMQ=OFF" "-DENABLE_QRCODE=OFF" "-DENABLE_UPNP=OFF" + "-DENABLE_CLANG_TIDY=OFF" ) # Allow usage of sanitizers by setting ECM_ENABLE_SANITIZERS @@ -269,6 +270,9 @@ "${BUILD_HEADER}" ) +include(ClangTidy) +add_clang_tidy_checks(util) + target_compile_definitions(util PUBLIC HAVE_CONFIG_H HAVE_BUILD_INFO) target_include_directories(util PUBLIC @@ -361,6 +365,8 @@ warnings.cpp ) +add_clang_tidy_checks(common) + target_link_libraries(common util secp256k1) # script library @@ -376,6 +382,8 @@ script/standard.cpp ) +add_clang_tidy_checks(script) + target_link_libraries(script common) # libbitcoinconsensus @@ -388,6 +396,8 @@ util/strencodings.cpp ) +add_clang_tidy_checks(bitcoinconsensus) + target_link_libraries(bitcoinconsensus script) include(InstallationHelper) @@ -460,6 +470,8 @@ validationinterface.cpp ) +add_clang_tidy_checks(server) + # This require libevent find_package(Event REQUIRED) @@ -515,6 +527,9 @@ # RPC client support add_library(rpcclient rpc/client.cpp) + +add_clang_tidy_checks(rpcclient) + target_link_libraries(rpcclient univalue util) # bitcoin-seeder @@ -527,6 +542,9 @@ # bitcoin-cli if(BUILD_BITCOIN_CLI) add_executable(bitcoin-cli bitcoin-cli.cpp) + + add_clang_tidy_checks(bitcoin-cli) + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_sources(bitcoin-cli PRIVATE bitcoin-cli-res.rc) endif() @@ -542,6 +560,9 @@ # bitcoin-tx if(BUILD_BITCOIN_TX) add_executable(bitcoin-tx bitcoin-tx.cpp) + + add_clang_tidy_checks(bitcoin-tx) + if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_sources(bitcoin-tx PRIVATE bitcoin-tx-res.rc) endif() @@ -556,6 +577,9 @@ # bitcoind add_executable(bitcoind bitcoind.cpp) + +add_clang_tidy_checks(bitcoind) + target_link_libraries(bitcoind server) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_sources(bitcoind PRIVATE bitcoind-res.rc) diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt --- a/src/bench/CMakeLists.txt +++ b/src/bench/CMakeLists.txt @@ -58,6 +58,9 @@ ${BENCH_DATA_GENERATED_HEADERS} ) +include(ClangTidy) +add_clang_tidy_checks(bitcoin-bench) + target_link_libraries(bitcoin-bench common bitcoinconsensus wallet server) if(BUILD_BITCOIN_WALLET) diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -16,6 +16,9 @@ siphash.cpp ) +include(ClangTidy) +add_clang_tidy_checks(crypto) + target_include_directories(crypto PRIVATE .. diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -110,6 +110,9 @@ qrc_bitcoin_locale.cpp ) +include(ClangTidy) +add_clang_tidy_checks(bitcoin-qt-base) + # Add the minimal integration plugin, and other plugins according to the target # platform. set(QT_PLUGIN_COMPONENTS QMinimalIntegrationPlugin) @@ -312,6 +315,8 @@ include(InstallationHelper) install_target(bitcoin-qt) +add_clang_tidy_checks(bitcoin-qt) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(BITCOINQT_BUNDLE_ICON "res/icons/bitcoin.icns") get_filename_component(BITCOINQT_BUNDLE_ICON_NAME diff --git a/src/qt/test/CMakeLists.txt b/src/qt/test/CMakeLists.txt --- a/src/qt/test/CMakeLists.txt +++ b/src/qt/test/CMakeLists.txt @@ -20,6 +20,9 @@ ../../test/test_bitcoin.cpp ) +include(ClangTidy) +add_clang_tidy_checks(test_bitcoin-qt) + target_link_libraries(test_bitcoin-qt bitcoin-qt-base Qt5::Test) # Wallet diff --git a/src/seeder/CMakeLists.txt b/src/seeder/CMakeLists.txt --- a/src/seeder/CMakeLists.txt +++ b/src/seeder/CMakeLists.txt @@ -10,6 +10,9 @@ dns.cpp ) +include(ClangTidy) +add_clang_tidy_checks(seeder-netprocessing) + target_link_libraries(seeder-netprocessing common bitcoinconsensus @@ -17,6 +20,8 @@ add_executable(bitcoin-seeder main.cpp) +add_clang_tidy_checks(bitcoin-seeder) + target_link_libraries(bitcoin-seeder common bitcoinconsensus seeder-netprocessing) include(BinaryTest) diff --git a/src/seeder/test/CMakeLists.txt b/src/seeder/test/CMakeLists.txt --- a/src/seeder/test/CMakeLists.txt +++ b/src/seeder/test/CMakeLists.txt @@ -13,6 +13,9 @@ seeder_tests.cpp ) +include(ClangTidy) +add_clang_tidy_checks(test_bitcoin-seeder) + target_link_libraries(test_bitcoin-seeder seeder-netprocessing ) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -178,6 +178,9 @@ ${BITCOIN_WALLET_TESTS} ) +include(ClangTidy) +add_clang_tidy_checks(test_bitcoin) + target_link_libraries(test_bitcoin rpcclient server) if(TARGET bitcoinconsensus-shared) target_link_libraries(test_bitcoin bitcoinconsensus-shared) diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/CMakeLists.txt @@ -25,6 +25,9 @@ walletutil.cpp ) +include(ClangTidy) +add_clang_tidy_checks(wallet) + target_link_libraries(wallet script univalue Event ${BDBXX_LIBRARY}) target_include_directories(wallet PUBLIC ${BDBXX_INCLUDE_DIR}) diff --git a/src/zmq/CMakeLists.txt b/src/zmq/CMakeLists.txt --- a/src/zmq/CMakeLists.txt +++ b/src/zmq/CMakeLists.txt @@ -9,6 +9,9 @@ zmqrpc.cpp ) +include(ClangTidy) +add_clang_tidy_checks(zmq) + find_package(ZeroMQ REQUIRED) target_include_directories(zmq PRIVATE ${ZMQ_INCLUDE_DIR}) target_link_libraries(zmq util ${ZMQ_LIBRARY})