| #!/usr/bin/env bash |
| # |
| # Run the include-what-you-use tool (iwyu) on a file in the webrtc source |
| # directory. |
| # |
| # The script uses a subsequent grep pass to remove #include files |
| # that are problematic to include. |
| # |
| # In order to handle include paths correctly, you need to provide |
| # a compile DB (aka compile_commands.json). |
| # You can create it in one of the following ways: |
| # "gn gen --export-compile-commands path/to/out" |
| # "tools/clang/scripts/generate_compdb.py -p path/to/out > compile_commands.json" |
| # If "out/Default" exists, the script will attempt to generate it for you. |
| # |
| # To get iwyu on Debian/glinux, do "sudo apt-get install iwyu". |
| |
| # Set this to 1 to get more debug information. |
| # Set this to 2 to also get a dump of the iwyu tool output. |
| DEBUG=0 |
| |
| set -e |
| if [ $DEBUG -gt 0 ]; then |
| set -x |
| fi |
| |
| error() { |
| echo "$*" >&2 |
| exit 1 |
| } |
| |
| find_alternates() { |
| for name in "$@" |
| do |
| name_path=$(which "${name}") |
| if [ ! -z "${name_path}" ]; then |
| echo ${name_path} |
| return 0 |
| fi |
| done |
| error "Could not find any of the tools '$@' in PATH." |
| return 1 |
| } |
| |
| IWYU_TOOL=$(find_alternates iwyu_tool iwyu_tool.py) |
| FIX_INCLUDE=$(find_alternates fix_include fix_includes.py) |
| FIX_INCLUDE_ARGS='' |
| IWYU_TOOL_DIR="${IWYU_TOOL_DIR:-tools_webrtc/iwyu}" |
| COMPILE_COMMANDS='' |
| |
| usage() { |
| echo "Usage: $0 [ -c compile-commands-file.json ] [-r] file.cc" |
| echo "Runs the IWYU and fix-include on a CC file and its associated .h file" |
| echo "Arguments:" |
| echo " -c compile-commands: Compiler command file" |
| echo " -r : Remove non-required includes from .h file" |
| echo " -h : Print this help message" |
| echo "(default command file: out/Default/compile_commands.json - this" |
| echo "will be generated if not present" |
| } |
| |
| while getopts 'c:rh' opts; do |
| case "${opts}" in |
| c) COMPILE_COMMANDS="${OPTARG}" ;; |
| r) FIX_INCLUDE_ARGS="${FIX_INCLUDE_ARGS} --nosafe_headers" ;; |
| h) usage; exit 1 ;; |
| *) error "Unexpected option ${opts}" ;; |
| esac |
| done |
| shift $(expr $OPTIND - 1 ) |
| |
| if [[ -z "$COMPILE_COMMANDS" ]]; then |
| if [ -d "out/Default" ]; then |
| if [ ! -f "out/Default/compile_commands.json" ]; then |
| gn gen --export-compile-commands out/Default |
| fi |
| COMPILE_COMMANDS="out/Default/compile_commands.json" |
| else |
| error "compile_commands.json must be passed." |
| fi |
| fi |
| |
| FILE="$1" |
| |
| if [ ! -f $FILE_CC ]; then |
| error "File $FILE is not found" |
| fi |
| |
| # Find the .h file that IWYU will modify, if any. |
| FILE_CC=$FILE |
| if [ -f $(dirname $FILE)/$(basename -s .cc $FILE).h ]; then |
| FILE_H=$(dirname $FILE)/$(basename -s .cc $FILE).h |
| else |
| FILE_H="" |
| fi |
| |
| tmpfile=$(realpath $(mktemp iwyu.XXXXXXX)) |
| trap 'rm -f -- "${tmpfile}"' EXIT |
| |
| # IWYU has a confusing set of exit codes. Discard it. |
| "$IWYU_TOOL" -p "$COMPILE_COMMANDS" "$FILE_CC" -- -Xiwyu --no_fwd_decls \ |
| -Xiwyu --mapping_file=../../$IWYU_TOOL_DIR/mappings.imp \ |
| >& ${tmpfile} || echo "IWYU done, code $?" |
| |
| if grep 'fatal error' ${tmpfile}; then |
| echo "iwyu run failed" |
| cat ${tmpfile} |
| exit 1 |
| else |
| if [ $DEBUG -gt 1 ]; then |
| cat ${tmpfile} |
| fi |
| # In compile_commands.json, the file name is recorded |
| # as a relative path to the build directory. |
| pushd "$(dirname "$COMPILE_COMMANDS")" || error "pushd failed" |
| "$FIX_INCLUDE" $FIX_INCLUDE_ARGS < ${tmpfile} || echo "Some files modified" |
| popd |
| fi |
| |
| grep -v -f tools_webrtc/iwyu/iwyu-filter-list $FILE_CC > $FILE_CC.new |
| mv $FILE_CC.new $FILE_CC |
| |
| if [ -n "$FILE_H" ]; then |
| grep -v -f tools_webrtc/iwyu/iwyu-filter-list $FILE_H > $FILE_H.new |
| mv $FILE_H.new $FILE_H |
| fi |
| |
| echo "Finished. Check diff, compile and git cl format before uploading." |