Don't Use include-what-you-use

· danra's blog

#tooling #C++

Don't use include-what-you-use.

For all these reasons, I stopped after integrating support on macOS, not bothering to add support on Linux, and definitely not bothering to add it on Windows (which IWYU appears to have limited support for).

In short, include-what-you-use is alpha quality, which is what the repo also clearly states.

In conclusion, IWYU probably isn't worth your time, except maybe in extreme cases, e.g., if your codebase makes no use of forward declarations and you want to change that. Wait for modules to become mainstream instead.

...Still want to run it anyway? OK.

  1. Install include-what-you-use (macOS):

    1brew install include-what-you-use  # will also install llvm
    
  2. Add a CMake option for enabling IWYU (as mentioned, it's very likely you would NOT want to always run it)

    1option(SR_ENABLE_IWYU "Enable include-what-you-use")
    2if (SR_ENABLE_IWYU)
    3    find_program(iwyu_path NAMES include-what-you-use REQUIRED)
    4endif()
    
  3. Add a CMake function for enabling IWYU on a target, and call as appropriate:

     1function(sr_setup_iwyu TARGET)
     2    if (NOT iwyu_path)
     3        return()
     4    endif()
     5    set(iwyu_options
     6        "-Xiwyu" "--mapping_file=<extra mapping file>"
     7        "-Xiwyu" "--keep=<as needed, e.g., headers with utility macros>"
     8        "-Xiwyu" "--quoted_includes_first"
     9        "-Xiwyu" "--cxx17ns"
    10        # Avoid extra Clang diagnostics from include-what-you-use (got some unhelpful false positives)
    11        "-w"
    12    )
    13    set_property(TARGET ${TARGET} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path};${iwyu_options}")
    14endfunction()
    

    In all but very simple projects, this would probably be better than just setting CMAKE_CXX_INCLUDE_WHAT_YOU_USE, which would analyze not just your own targets but also all 3rd-party dependencies.

    As for 3rd-party sources included in your targets, you can use the SKIP_LINTING flag to avoid analyzing those:

    1set_property(SOURCE ${SOURCES_TO_SKIP} PROPERTY SKIP_LINTING ON)
    
  4. Setup a build system using a generator that supports IWYU (currently only Makefile and Ninja):

    1cmake -B build -G "Ninja Multi-Config"
    
  5. Build and record the output for some configuration:

    1cmake --config <config> --build build | tee out.txt
    
  6. Run fix_includes.py:

    1cat out.txt | fix_includes.py --nosafe_headers --keep_iwyu_namespace_format --noreorder
    
  7. The includes order would likely be incorrect, so run git-clang-format to amend. Take special care in files which have any preprocessor conditionals around includes: it's very likely IWYU would add missing includes not where you intend.

  8. Review IWYU's work and fix as needed.

  9. Repeat the last four steps until you get no warnings. As mentioned, sometimes new warnings can pop up after you handle all the ones in a previous batch.