Search code examples
c++header-filesbuild-time

Header inclusion optimization


Is there an automatic way to optimize inclusion of header files in C++, so that compilation time is improved ? With the word "automatic" I mean a tool or program. Is it possible to find which headers files are obsolete (e.g exposed functionality is not used) ?

Edit: Having each include header "included only once is one important thing, but is there a way to even change the contents of files so that frequently used "functionality" is on specific includes and less frequently used functionality is on other includes? Am i asking too much ? Unfortunately, we are talking about an existing code base with thousands of files. Could it be a refactoring tool what I am actually asking for ?


Solution

  • Update

    I think what you really want is "include what you use" rather than a minimal set of headers. IWYU means forward declare as much as possible, and include headers that directly declare the symbols you use. You cannot mindlessly convert a file to be IWYU clean as it may no longer compile. When that occurs, you need to find the missing header and add it. However, if every file is IWYU clean your compiles will be faster overall even if you have to add headers occasionally. Not to mention you headers will be more meaningful/self-documenting.

    As my previous answer points out it is technically possible to include even fewer headers than necessary for IWYU, but it's generally a waste of time.

    Now if only there was a tool to most of the IWYU refactoring grunt work for you :)


    I had considered a creating/using a tool like this once. The idea is to use binary search and repeated compilation to find the minimal set of includes. Upon further investigation it didn't seem that useful.

    Some issues:

    • Changing the included header files can change the behavior, and still allow the file to compile. One example in particular, if you defined your own std::swap in a separate header file. You could remove that header and your code would still compile using the default std::swap implementation. However, the std::swap may be: inefficient, cause a runtime error, or worse produce subtly wrong logic.

    • Sometimes a header file inclusion works as documentation. For instance, to used std::foreach, often including <vector> is sufficient to get it to compile. The code is more meaningful with the extra #include <algorithm>.

    • The minimal compilation set may not be portable, between compilers or compiler versions. Using the std::foreach example again, there is no guarantee that std::foreach will provided in by <vector>.

    • The minimal set of includes may not affect compile time significantly anyway. Visual studio and gcc support #pragma once which make repeated included essentially non-existent performance wise. And at least gcc's preprocessor has been optimized to process include guards very fast (as fast as #pragma once).