1#!/bin/bash -u 2 3if [[ $# -lt 2 || $# -gt 4 ]]; then 4 echo "Usage: $0 <build dir> <file or dir path> [rejects dir] [checks]" 5 echo " - <build dir> has to be a LLVM build directory (you should use CCACHE!)." 6 echo " - <file or dir path> is the path that contains the .cpp files to update." 7 echo " - [rejects dir] is a directory where rejected patch (build failure) will be stored." 8 echo " - [checks] is an optional space-separated list of check to use instead of auto-detecting" 9 echo " Also define the env var CLANG_TIDY the path to use for the clang-tidy binary (default to 'clang-tidy' in the PATH)" 10 echo " Also define the env var TIMING_TIDY to 'time' to prefix clang-tidy execution with it" 11 echo "" 12 echo "This tool will execute clang-tidy on every .cpp file in the provided path and" 13 echo "rerun the tests. On success, a commit is added to the repo for each individual" 14 echo "pair <clang-tidy check, file>." 15 exit 1 16fi 17BUILD_DIR=$1 18SRCS=$2 19REJECT_DIR=${3:-} 20PRESET_CHECKS=${4:-} 21SRC_DIR=$PWD 22if [[ -v CLANG_TIDY ]] && [[ ! -z "$CLANG_TIDY" ]] ; then 23 CLANG_TIDY=$(realpath $CLANG_TIDY) 24 if [[ ! -f "$CLANG_TIDY" ]]; then 25 echo "Invalid path '$CLANG_TIDY'" 26 exit 1 27 fi 28else 29 CLANG_TIDY=clang-tidy 30fi 31TIMING_TIDY=${TIMING_TIDY:-} 32echo "Using: '$CLANG_TIDY" 33 34if [[ ! -z "$REJECT_DIR" ]] && [[ ! -d "$REJECT_DIR" ]]; then 35 echo "Expects 'rejects dir' to be a directory, got '$REJECT_DIR'" 36 exit 1 37fi 38 39ensure_clean_build() { 40 git reset --hard HEAD 41 time ninja -C $BUILD_DIR check-mlir-build-only > ${REJECT_DIR}/ninja.clean.log 2>&1 42 if [[ $? != 0 ]] ; then 43 echo "-- Build failed on clean state, cleaning TableGen files and retry" 44 # Reinitialize the TableGen generated file to have a clean state 45 find $BUILD_DIR/tools/mlir/ | grep '\.inc' | while read file ; do rm $file ; done 46 time ninja -C $BUILD_DIR check-mlir-build-only > ${REJECT_DIR}/ninja.clean.log 2>&1 47 if [[ $? != 0 ]] ; then 48 echo "check-mlir-build-only failed on clean state! (see ninja.clean.log)" 49 git status 50 exit 1 51 fi 52 fi 53} 54 55tmpfile=$(mktemp /tmp/mhlo-temp-checks.XXXXXX) 56find $SRCS | grep ".cpp$" | sort | while read file ; do 57 echo "================================" 58 echo "======= Processing $file =======" 59 date 60 echo "================================" 61 CHECKS= 62 if [[ ! -z "$PRESET_CHECKS" ]]; then 63 CHECKS="$PRESET_CHECKS" 64 else 65 CHECKS=$($CLANG_TIDY $file -p $BUILD_DIR --list-checks \ 66 | grep -v "Enabled checks:" | grep -v "^$" \ 67 | while read check ; do echo -n "${check} " ; done;) 68 fi 69 echo "-----------------------------------" 70 echo "-- Reset state before applying all checks on file $file" 71 ensure_clean_build 72 73 echo "-----------------------------------" 74 echo "-- Apply all checks on file $file" 75 echo "$TIMING_TIDY $CLANG_TIDY -p $BUILD_DIR $file -fix -fix-errors" 76 $TIMING_TIDY $CLANG_TIDY -p $BUILD_DIR $file -fix -fix-errors \ 77 | grep "warning:.*\]$" | sed -r 's#.*\[(.*)]$#\1#' | sort -u > $tmpfile 78 git clang-format -f 79 if [[ $(git diff --stat) == '' ]]; then 80 echo 'Nothing was applied, skip' 81 continue 82 fi 83 echo "-----------------------------------" 84 echo "-- Got some diff, run one check at a time now" 85 cat $tmpfile | while read check ; do 86 echo "-----------------------------------" 87 echo "-- Reset state before applying check $check on file $file" 88 ensure_clean_build 89 90 echo "-----------------------------------" 91 echo "-- Apply check $check on file $file" 92 echo "$TIMING_TIDY $CLANG_TIDY -p $BUILD_DIR $file --checks="-*,$check" -fix -fix-errors" 93 { $TIMING_TIDY $CLANG_TIDY -p $BUILD_DIR $file --checks="-*,$check" -fix -fix-errors ; } 2>&1 94 git clang-format -f 95 if [[ $(git diff --stat) == '' ]]; then 96 echo 'Nothing was applied, skip' 97 continue 98 fi 99 echo "-----------------------------------" 100 echo "-- Test check $check on file $file" 101 # Clang-tidy sometimes update files in the build directory, erase the .inc file generate by tablegen 102 # to force them to be regenerated now. 103 find $BUILD_DIR/tools/mlir/ | grep '\.inc' | while read file ; do rm $file ; done 104 ninja -C $BUILD_DIR check-mlir > ${REJECT_DIR}/ninja.${check}.$(basename $file).log 2>&1 105 if [[ $? != 0 ]] ; then 106 echo "check-mlir failed! (see ninja.${check}.${file}.log)" 107 [[ ! -z "$REJECT_DIR" ]] && git diff > "${REJECT_DIR}/${check}_$(basename ${file}).reject.diff" 108 continue 109 fi 110 echo "-----------------------------------" 111 echo "-- Success, commit changes for check $check on file $file" 112 git clang-format -f 113 114 git commit -a -m "Apply clang-tidy fixes for $check in $(basename $file) (NFC)" 115 done 116done 117