xref: /aosp_15_r20/external/webrtc/tools_webrtc/iwyu/apply-iwyu (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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