include-what-you-use (a.k.a. IWYU) is a clang tool that tells you which #include statements should be added and removed from a file. Nicholas Cameron used it to speed up the building of gfx/layers by 12.5%. I’ve also used it quite a bit within SpiderMonkey; I’ve seen smaller build speed improvements but I’ve also been doing it in chunks over time. Ms2ger started a tracking bug for all places where IWYU has been used in Mozilla code.

Ehsan asked for instructions on setting up IWYU. There are official instructions, but I thought it might be helpful to document exactly what I did.

First, here is how I installed clang, based on Ehsan’s instructions. I put the source code under $HOME/local/src and installed the build under $HOME/local .

mkdir $HOME/local/src cd $HOME/local/src svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm cd llvm/tools svn co http://llvm.org/svn/llvm-project/cfe/trunk clang cd ../.. mkdir build cd build/ ../configure --enable-optimized --disable-assertions --prefix=$HOME/local make sudo make install

Then I followed the “Building in-tree” instructions. The first part is to get the IWYU code.

cd $HOME/local/src/llvm/tools/clang/tools svn checkout http://include-what-you-use.googlecode.com/svn/trunk/ include-what-you-use

The second part was to do the following steps.

Edit tools/clang/tools/Makefile and add |include-what-you-use| to the DIRS variable.

Edit tools/clang/tools/CMakeLists.txt and add |add_subdirectory(include-what-you-use)|.

Re-build clang as per the above instructions.

After that, configure a Mozilla tree for a clang build and then run make with the following options: -j1 -k CXX=/home/njn/local/src/llvm/build/Release/bin/include-what-you-use . I’m not certain if the -j1 is necessary, but since IWYU spits out lots of output, it seemed wise. The -k tells make to keep building even after errors; for some reason, IWYU triggers compilation failure on every file it looks at.

Pipe the output to a file, and you’ll see lots of stuff like this.

../jsarray.h should add these lines: #include <stdint.h> // for uint32_t #include <sys/types.h> // for int32_t #include "dist/include/js/RootingAPI.h" // for HandleObject, Handle, etc #include "jsapi.h" // for Value, HandleObject, etc #include "jsfriendapi.h" // for JSID_TO_ATOM #include "jstypes.h" // for JSBool #include "vm/String.h" // for JSAtom namespace JS { class Value; } namespace js { class ExclusiveContext; } struct JSContext; ../jsarray.h should remove these lines: The full include-list for ../jsarray.h: #include <stdint.h> // for uint32_t #include <sys/types.h> // for int32_t #include "dist/include/js/RootingAPI.h" // for HandleObject, Handle, etc #include "jsapi.h" // for Value, HandleObject, etc #include "jsfriendapi.h" // for JSID_TO_ATOM #include "jsobj.h" // for JSObject (ptr only), etc #include "jspubtd.h" // for jsid #include "jstypes.h" // for JSBool #include "vm/String.h" // for JSAtom namespace JS { class Value; } namespace js { class ArrayObject; } // lines 44-44 namespace js { class ExclusiveContext; } struct JSContext;

I focused on addressing the “should remove these lines” #includes, and I did it manually. There’s also a script you can use to automatically do everything for you; I don’t know how well it works.

Note that IWYU’s output is just plain wrong about 5% of the time — i.e. it says you can remove #includes that you clearly cannot. (A lot of the time this seems to be because it hasn’t realized that a macro is needed.) I also found that, while it produced output for all .cpp files, it only produced output for some of the .h files. No idea why. Finally, it doesn’t know about local idioms; in particular, if you have platform-dependent code, its suggestions are often terrible because it only sees the files for the platform you are building on.

Good luck!