1#!/usr/bin/env bash 2# 3# Run the include-what-you-use tool (iwyu) on a file in the webrtc source 4# directory. 5# 6# The script uses a subsequent grep pass to remove #include files 7# that are problematic to include. 8# 9# In order to handle include paths correctly, you need to provide 10# a compile DB (aka compile_commands.json). 11# You can create it in one of the following ways: 12# "gn gen --export-compile-commands path/to/out" 13# "tools/clang/scripts/generate_compdb.py -p path/to/out > compile_commands.json" 14# If "out/Default" exists, the script will attempt to generate it for you. 15# 16# To get iwyu on Debian/glinux, do "sudo apt-get install iwyu". 17 18# Set this to 1 to get more debug information. 19# Set this to 2 to also get a dump of the iwyu tool output. 20DEBUG=0 21 22set -e 23if [ $DEBUG -gt 0 ]; then 24 set -x 25fi 26 27error() { 28 echo "$*" >&2 29 exit 1 30} 31 32find_alternates() { 33 for name in "$@" 34 do 35 name_path=$(which "${name}") 36 if [ ! -z "${name_path}" ]; then 37 echo ${name_path} 38 return 0 39 fi 40 done 41 error "Could not find any of the tools '$@' in PATH." 42 return 1 43} 44 45IWYU_TOOL=$(find_alternates iwyu_tool iwyu_tool.py) 46FIX_INCLUDE=$(find_alternates fix_include fix_includes.py) 47FIX_INCLUDE_ARGS='' 48IWYU_TOOL_DIR="${IWYU_TOOL_DIR:-tools_webrtc/iwyu}" 49COMPILE_COMMANDS='' 50 51usage() { 52 echo "Usage: $0 [ -c compile-commands-file.json ] [-r] file.cc" 53 echo "Runs the IWYU and fix-include on a CC file and its associated .h file" 54 echo "Arguments:" 55 echo " -c compile-commands: Compiler command file" 56 echo " -r : Remove non-required includes from .h file" 57 echo " -h : Print this help message" 58 echo "(default command file: out/Default/compile_commands.json - this" 59 echo "will be generated if not present" 60} 61 62while getopts 'c:rh' opts; do 63 case "${opts}" in 64 c) COMPILE_COMMANDS="${OPTARG}" ;; 65 r) FIX_INCLUDE_ARGS="${FIX_INCLUDE_ARGS} --nosafe_headers" ;; 66 h) usage; exit 1 ;; 67 *) error "Unexpected option ${opts}" ;; 68 esac 69done 70shift $(expr $OPTIND - 1 ) 71 72if [[ -z "$COMPILE_COMMANDS" ]]; then 73 if [ -d "out/Default" ]; then 74 if [ ! -f "out/Default/compile_commands.json" ]; then 75 gn gen --export-compile-commands out/Default 76 fi 77 COMPILE_COMMANDS="out/Default/compile_commands.json" 78 else 79 error "compile_commands.json must be passed." 80 fi 81fi 82 83FILE="$1" 84 85if [ ! -f $FILE_CC ]; then 86 error "File $FILE is not found" 87fi 88 89# Find the .h file that IWYU will modify, if any. 90FILE_CC=$FILE 91if [ -f $(dirname $FILE)/$(basename -s .cc $FILE).h ]; then 92 FILE_H=$(dirname $FILE)/$(basename -s .cc $FILE).h 93else 94 FILE_H="" 95fi 96 97tmpfile=$(realpath $(mktemp iwyu.XXXXXXX)) 98trap 'rm -f -- "${tmpfile}"' EXIT 99 100# IWYU has a confusing set of exit codes. Discard it. 101"$IWYU_TOOL" -p "$COMPILE_COMMANDS" "$FILE_CC" -- -Xiwyu --no_fwd_decls \ 102 -Xiwyu --mapping_file=../../$IWYU_TOOL_DIR/mappings.imp \ 103 >& ${tmpfile} || echo "IWYU done, code $?" 104 105if grep 'fatal error' ${tmpfile}; then 106 echo "iwyu run failed" 107 cat ${tmpfile} 108 exit 1 109else 110 if [ $DEBUG -gt 1 ]; then 111 cat ${tmpfile} 112 fi 113 # In compile_commands.json, the file name is recorded 114 # as a relative path to the build directory. 115 pushd "$(dirname "$COMPILE_COMMANDS")" || error "pushd failed" 116 "$FIX_INCLUDE" $FIX_INCLUDE_ARGS < ${tmpfile} || echo "Some files modified" 117 popd 118fi 119 120grep -v -f tools_webrtc/iwyu/iwyu-filter-list $FILE_CC > $FILE_CC.new 121mv $FILE_CC.new $FILE_CC 122 123if [ -n "$FILE_H" ]; then 124 grep -v -f tools_webrtc/iwyu/iwyu-filter-list $FILE_H > $FILE_H.new 125 mv $FILE_H.new $FILE_H 126fi 127 128echo "Finished. Check diff, compile and git cl format before uploading." 129