I released a new software tool today. The surprise about this one is that it turns out to be consistently more useful than I expected. And thereby hangs a tale.
The tool is deheader. What it does is find, and optionally remove, #include files that their C source file does not actually require to compile. It does this by the brutally simple method of repeatedly attempting to recompile each source with more #includes removed than on previous passes. There are some bits of cleverness about the order #includes are test-deleted in, and it avoids some cases likely to lead to false positives – notably, includes within the scope of #if/#endif. But, basically, it just brute-forces its way through.
The benefit of removing these unused includes is threefold. First, it reduces build time – sometimes by a lot, especially on C++ projects. Secondly, it may cut the runtime size of your binary modules. Third, by removing noise from #include lists it makes clearer what each module’s dependencies actually are.
The first surprise is that even on quite large projects this check doesn’t take forever. On modern hardware, single-module C compiles are very fast. I’ve learned from watching deheader runs on a couple of largish C projects that, out of total build time, the compiler consumes a smaller fraction – and the linker a quite a bit larger fraction – than I would have thought beforehand.
C++ is another story; due to templates, the average of compile times is greater and the variance in compile times is much larger – but the gains from removing unused headers are proportionately larger, too. Notwithstanding templates in the mix, complete deheader runs have (surprisingly) tolerable time to completion even on projects the size of Battle For Wesnoth.
The second surprise is that there a lot more unused includes out there than I expected. When I ran deheader on the gpsd sources this afternoon, I expected maybe a couple dozen hits. I got over 200. Running the first prototype on Battle For Wesnoth back in late 2008 turned up a preposterous pile of them, I think over a thousand.
Evidently programmers not only drop a lot of #includes in place by reflex, but are very poor at noticing when code refactoring has made them unnecessary. It’s a quiet error, relatively harmless, and we have other things to pay attention to.
I use a guillotine as the deheader project’s logo (due props to hacker/artist sirea, who released it under CC-by). Off with their header files!
If you maintain a C or C++ project, I recommend running this tool on it. I predict the amount of #include cruft you clear out will surprise you.