1#!/bin/bash -e 2 3# Copyright 2022 Google Inc. All rights reserved. 4 5# Wrapper of clang-tidy 6 7# Use case #1: by RBE input processor to get resource dir. 8# Command: 9# clang-tidy.sh --version -- -print-resource-dir 10# Outputs: 11# same as clang-tidy --version -- -print-resource-dir 12 13# Use case #2: by soong generated ninja build rules. 14# Calls clang-tidy and touch output .tidy file. 15# Calls clang or clang++ to generate .tidy.d file. 16# Environment: 17# CLANG_CMD: 'clang' or 'clang++' 18# TIDY_FILE: path to output .tidy file 19# TIDY_TIMEOUT: optional for clang-tidy 20# Arguments: # same as clang-tidy 21# <in-file-path> (required, input file) 22# <clang-tidy flags> (optional) 23# "--" (required to separate arguments) 24# <clang/clang++ flags> (optional) 25# Outputs: 26# .../*.tidy (the output file) 27# .../*.tidy.d (the dependent file is output file plus .d suffix) 28# stdout and stderr from clang-tidy 29# stdout and stderr from clang/clang++ if clang-tidy succeeds 30 31BIN_DIR=`dirname $0` 32for x in "$@"; do 33 if [ "$x" == "--version" ]; then 34 exec "${BIN_DIR}/clang-tidy" "$@" 35 fi 36done 37 38usage() { 39 cat <<EOF 40Environment Variable: 41 required: CLANG_CMD={clang|clang++} 42 required: TIDY_FILE=<path to the output .tidy file> 43 optional: TIDY_TIMEOUT=<seconds> 44Usage: clang-tidy.sh <file> <clang-tidy flags> -- <clang/clang++ flags> 45EOF 46 exit 1 47} 48 49INF="$1" 50if [ -z "${CLANG_CMD}" ]; then 51 echo "ERROR: CLANG_CMD environment variable must be set" 52 usage 53fi 54if [ "${CLANG_CMD}" != "clang" -a "${CLANG_CMD}" != "clang++" ]; then 55 echo "ERROR: CLANG_CMD must be 'clang' or 'clang++'" 56 usage 57fi 58if [ -z "${TIDY_FILE}" ]; then 59 echo "ERROR: TIDY_FILE environment variable must be set" 60 usage 61fi 62 63ARGS=("$@") 64NARGS=${#@} 65# call clang-tidy with all arguments 66TIDY_CLANG_FLAGS=("${ARGS[@]}") 67 68# find "--" in ARGS and set CLANG_FLAGS 69LONGDASH="" 70for idx in ${!ARGS[@]}; do 71 if [ "${ARGS[$idx]}" == "--" ]; then 72 LONGDASH=$idx 73 fi 74done 75if [ -z "${LONGDASH}" ]; then 76 echo "ERROR: missing '--' argument" 77 usage 78fi 79# call clang with clang flags, after INF 80N=$(expr $LONGDASH + 1) 81CLANG_FLAGS=("${ARGS[@]:$N:$NARGS}") 82# add more flags to generate .tidy.d file 83CLANG_FLAGS+=("-E" "-o" "/dev/null" "-MQ" "${TIDY_FILE}" "-MD" "-MF" "${TIDY_FILE}.d") 84 85TIDY_STDOUT="${TIDY_FILE}.stdout" 86TIDY_STDERR="${TIDY_FILE}.stderr" 87CLANG_STDOUT="${TIDY_FILE}.d.stdout" 88CLANG_STDERR="${TIDY_FILE}.d.stderr" 89 90OUT_DIR=`dirname ${TIDY_FILE}` 91mkdir -p ${OUT_DIR} 92 93call_clang() { 94 "${BIN_DIR}/${CLANG_CMD}" "${INF}" "${CLANG_FLAGS[@]}" \ 95 > ${CLANG_STDOUT} 2> ${CLANG_STDERR} & \ 96 CLANG_PID=$! 97} 98 99call_clang_tidy() { 100 "${BIN_DIR}/clang-tidy" "${TIDY_CLANG_FLAGS[@]}" \ 101 > ${TIDY_STDOUT} 2> ${TIDY_STDERR} & \ 102 TIDY_PID=$! 103} 104 105rm -f ${TIDY_FILE} ${TIDY_STDOUT} ${TIDY_STDERR} ${CLANG_STDOUT} ${CLANG_STDERR} 106call_clang 107call_clang_tidy 108 109CLANG_RESULT=0 110TIDY_RESULT=0 111wait ${CLANG_PID} || CLANG_RESULT=$? 112if [ "${CLANG_RESULT}" == 0 ]; then 113 # RBE put some files in /b/f/w/, which should be removed in .d files. 114 # Or ninja dependency check will not find them and run this script again. 115 sed -i -e 's:/b/f/w/::' ${TIDY_FILE}.d 116fi 117wait ${TIDY_PID} || TIDY_RESULT=$? 118 119cat ${TIDY_STDOUT} 120cat ${TIDY_STDERR} 1>&2 121if [ "${TIDY_RESULT}" == 0 ]; then 122 touch ${TIDY_FILE} 123 # dump clang/clang++ output and use its exit code 124 cat ${CLANG_STDOUT} 125 cat ${CLANG_STDERR} 1>&2 126 TIDY_RESULT=${CLANG_RESULT} 127else 128 # ignore clang/clang++ output 129 rm -f ${TIDY_FILE}.d 130fi 131 132rm -f ${TIDY_STDOUT} ${TIDY_STDERR} ${CLANG_STDOUT} ${CLANG_STDERR} 133exit ${TIDY_RESULT} 134