From a7e6f3f07258e02155f20be4068249b27b837f25 Mon Sep 17 00:00:00 2001 From: Michael Richters Date: Thu, 7 Apr 2022 14:04:10 -0500 Subject: [PATCH] When running IWYU, process source files before headers Suppose the following: `foo.cpp` refers to the symbol `Bar`, declared in `bar.h`. `foo.h` includes `bar.h`. `foo.cpp` includes `foo.h`, but not `bar.h`. `foo.h` does not refer to any symbols declared in `bar.h`. If we process `foo.h` first, `#include "bar.h"` will be removed, causing IWYU to fail with an error when it tries to process `foo.cpp`, but if we process them in the other order, `foo.cpp` will get that include before it gets removed from `foo.h`. This change sorts the files to be processed, putting all cpp files first, then all header files, minimizing that problem. We could do even better by saving the results from `include-what-you-use` for every file, then going back and calling `fix_includes.py` on each of them, but I don't think it's worth it. Signed-off-by: Michael Richters --- bin/fix-header-includes | 4 +++- bin/iwyu.py | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/bin/fix-header-includes b/bin/fix-header-includes index c25d2706..13c105cb 100755 --- a/bin/fix-header-includes +++ b/bin/fix-header-includes @@ -3,4 +3,6 @@ : "${KALEIDOSCOPE_DIR:=$(pwd)}" cd "${KALEIDOSCOPE_DIR}" || exit 1 -git ls-files -m | grep -E '\.(h|cpp)$' | xargs "${KALEIDOSCOPE_DIR}"/bin/iwyu.py +# Process sources first, then headers to minimize errors from removed includes +git ls-files -m | grep -E '\.(cpp|ino)$' | xargs "${KALEIDOSCOPE_DIR}"/bin/iwyu.py +git ls-files -m | grep -E '\.h$' | xargs "${KALEIDOSCOPE_DIR}"/bin/iwyu.py diff --git a/bin/iwyu.py b/bin/iwyu.py index 15cd81a2..93c6372e 100755 --- a/bin/iwyu.py +++ b/bin/iwyu.py @@ -296,12 +296,24 @@ def main(): # ---------------------------------------------------------------------- regex = re.compile(opts.regex) + # Process source files first, then header files, because a source file might have been + # relying on a header included by its associated header, but which that header does not + # need on its own. In this case, if we process the header first, IWYU won't be able to + # parse the source file, and we'll get an error, but if we do them in the other order, + # it'll be fine. + source_files = [] + header_files = [] + for target_file in (_ for t in targets for _ in build_target_list(t, regex)): + if target_file.endswith('.cpp') or target_file.endswith('.ino'): + source_files.append(target_file) + else: + header_files.append(target_file) exit_code = 0 - for src in (_ for t in targets for _ in build_target_list(t, regex)): - if src in ignores: - logging.info("Skipping ignored file: %s", os.path.relpath(src)) + for target_file in source_files + header_files: + if target_file in ignores: + logging.info("Skipping ignored file: %s", os.path.relpath(target_file)) continue - if not run_iwyu(os.path.relpath(src), iwyu_cmd, fix_includes_cmd): + if not run_iwyu(os.path.relpath(target_file), iwyu_cmd, fix_includes_cmd): exit_code = 1 return exit_code