Don't use include-what-you-use.
- It produces a LOT of output for a project where it's first added, so it takes quite a lot of work to adapt because all of the work has to be reviewed (especially on the first run).
- After actually doing all that work in a couple of Sound Radix's projects, the end result was that it made almost no difference to the CI build time.
- Running IWYU's analysis slows down compilation considerably, so even for already-adapted projects it doesn't make sense to run by default either locally or in CI, since one of the main goals of applying IWYU in the first place is making builds faster!
- It requires separately testing debug, release, and any other build configurations with differing macro definitions.
- It requires making manual fixes to accommodate changes incompatible with build platforms other than the one you run IWYU on.
- It can't take expanded macros into account, so header files defining utility macros have to be manually marked to keep.
- It sometimes just wrongly removes needed includes, requiring manual fixes.
- Running multiple iterations might be needed to get to a stable state where no more warnings are found.
- It requires writing extra mappings for system headers it isn't aware of (was missing a few on macOS), as well as for 3rd-party frameworks such as JUCE.
- It sometimes crashes.
- For C headers, it seems to randomly decide whether to include the
<cxxx>
or<xxx.h>
version. This one isn't important at all, except if you're running IWYU you're probably somewhat pedantic? So just know it wouldn't get you those pristine includes you might be looking for.
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.
-
Install include-what-you-use (macOS):
1brew install include-what-you-use # will also install llvm
-
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()
-
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)
-
Setup a build system using a generator that supports IWYU (currently only
Makefile
andNinja
):1cmake -B build -G "Ninja Multi-Config"
-
Build and record the output for some configuration:
1cmake --config <config> --build build | tee out.txt
-
Run
fix_includes.py
:1cat out.txt | fix_includes.py --nosafe_headers --keep_iwyu_namespace_format --noreorder
-
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. -
Review IWYU's work and fix as needed.
-
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.