include-what-you-use
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseInclude What You Use (IWYU)
Include What You Use (IWYU)
Purpose
用途
Guide agents through using IWYU to reduce unnecessary directives, interpret IWYU reports and mapping files, decide between forward declarations and full includes, and integrate IWYU into CMake builds to reduce compilation cascades in large codebases.
#include指导开发者使用IWYU减少不必要的指令,解读IWYU报告和映射文件,选择前向声明还是完整头文件包含,并将IWYU集成到CMake构建流程中,以减少大型代码库中的编译连锁反应。
#includeTriggers
触发场景
- "How do I use include-what-you-use?"
- "How do I reduce my C++ compilation times by fixing includes?"
- "How do I interpret IWYU output?"
- "Should I use a forward declaration or include?"
- "How do I integrate IWYU with CMake?"
- "What is a compilation cascade and how do I avoid it?"
- "我如何使用include-what-you-use?"
- "我如何通过修复头文件包含来缩短C++编译时间?"
- "我如何解读IWYU的输出结果?"
- "我应该使用前向声明还是头文件包含?"
- "我如何将IWYU与CMake集成?"
- "什么是编译连锁反应,我该如何避免?"
Workflow
操作流程
1. Install and run IWYU
1. 安装并运行IWYU
bash
undefinedbash
undefinedInstall
Install
apt-get install iwyu # Ubuntu/Debian
brew install include-what-you-use # macOS
apt-get install iwyu # Ubuntu/Debian
brew install include-what-you-use # macOS
Run on a single file
Run on a single file
iwyu -Xiwyu --error main.cpp 2>&1
iwyu -Xiwyu --error main.cpp 2>&1
Run via compile_commands.json
Run via compile_commands.json
iwyu_tool.py -p build/ src/main.cpp 2>&1 | tee iwyu.log
iwyu_tool.py -p build/ src/main.cpp 2>&1 | tee iwyu.log
Run on entire project
Run on entire project
iwyu_tool.py -p build/ 2>&1 | tee iwyu.log
undefinediwyu_tool.py -p build/ 2>&1 | tee iwyu.log
undefined2. CMake integration
2. CMake集成
cmake
undefinedcmake
undefinedCMakeLists.txt — use IWYU as include checker during build
CMakeLists.txt — use IWYU as include checker during build
find_program(IWYU_PROGRAM NAMES include-what-you-use iwyu)
if(IWYU_PROGRAM)
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
${IWYU_PROGRAM}
-Xiwyu --mapping_file=${CMAKE_SOURCE_DIR}/iwyu.imp
-Xiwyu --no_comments
)
endif()
```bashfind_program(IWYU_PROGRAM NAMES include-what-you-use iwyu)
if(IWYU_PROGRAM)
set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
${IWYU_PROGRAM}
-Xiwyu --mapping_file=${CMAKE_SOURCE_DIR}/iwyu.imp
-Xiwyu --no_comments
)
endif()
```bashBuild with IWYU analysis
Build with IWYU analysis
cmake -S . -B build -DCMAKE_CXX_COMPILER=clang++
cmake --build build 2>&1 | tee iwyu.log
undefinedcmake -S . -B build -DCMAKE_CXX_COMPILER=clang++
cmake --build build 2>&1 | tee iwyu.log
undefined3. Interpreting IWYU output
3. 解读IWYU输出
text
main.cpp should add these lines:
#include <string> // for std::string
#include "mylib/widget.h" // for Widget
main.cpp should remove these lines:
- #include <vector> // lines 5-5
- #include "internal/detail.h" // lines 8-8
The full include-list for main.cpp:
#include <iostream> // for std::cout
#include <string> // for std::string
#include "mylib/widget.h" // for Widget
---Reading the output:
- should add: headers providing symbols used but not yet included
- should remove: headers included but whose symbols aren't used directly
- The full include-list: what the final header list should look like
text
main.cpp should add these lines:
#include <string> // for std::string
#include "mylib/widget.h" // for Widget
main.cpp should remove these lines:
- #include <vector> // lines 5-5
- #include "internal/detail.h" // lines 8-8
The full include-list for main.cpp:
#include <iostream> // for std::cout
#include <string> // for std::string
#include "mylib/widget.h" // for Widget
---输出解读:
- should add:提供了已使用但尚未包含的符号的头文件
- should remove:已包含但未直接使用其符号的头文件
- The full include-list:最终应有的头文件列表
4. Apply IWYU fixes automatically
4. 自动应用IWYU修复
bash
undefinedbash
undefinedfix_include script (comes with IWYU)
fix_include script (comes with IWYU)
fix_include < iwyu.log
fix_include < iwyu.log
Options
Options
fix_include --nosafe_headers < iwyu.log # more aggressive — also removes system headers
fix_include --comments < iwyu.log # preserve // comments in includes
fix_include --dry_run < iwyu.log # preview changes without applying
fix_include --nosafe_headers < iwyu.log # more aggressive — also removes system headers
fix_include --comments < iwyu.log # preserve // comments in includes
fix_include --dry_run < iwyu.log # preview changes without applying
Limit to specific files
Limit to specific files
fix_include --only_re='src/.*.cpp' < iwyu.log
fix_include --only_re='src/.*.cpp' < iwyu.log
Run and apply in one pipeline
Run and apply in one pipeline
iwyu_tool.py -p build/ 2>&1 | fix_include
undefinediwyu_tool.py -p build/ 2>&1 | fix_include
undefined5. Forward declarations vs full includes
5. 前向声明 vs 完整头文件包含
IWYU prefers forward declarations (class/struct declarations without definition) when the full type isn't needed:
cpp
// full_include.h — DON'T include this if only a pointer is used
#include "widget.h" // full definition: Widget members, vtable, etc.
// forward_decl.h — OK when Widget* or Widget& is sufficient
class Widget; // forward declaration
void process(Widget *w); // pointer: forward decl is enough
// When forward declaration is sufficient:
// - Pointer or reference parameter: Widget*, Widget&
// - Return type as pointer: Widget*
// - Base class declared elsewhere (but defined in .cpp)
// When full include is required:
// - Inheriting from Widget: class MyWidget : public Widget
// - Accessing Widget members: w.field, w.method()
// - Creating Widget instances: Widget w;
// - Sizeof(Widget)
// - Template instantiation: std::vector<Widget>cpp
// IWYU-friendly header
#pragma once
class Widget; // forward declare (saves downstream compilation)
class Container {
Widget *head_; // pointer: forward decl is enough
public:
void add(Widget *w);
Widget *get(int idx);
};
// Container.cpp includes "widget.h" — only .cpp pays the compile cost当不需要完整类型定义时,IWYU优先推荐前向声明(不含定义的类/结构体声明):
cpp
// full_include.h — DON'T include this if only a pointer is used
#include "widget.h" // full definition: Widget members, vtable, etc.
// forward_decl.h — OK when Widget* or Widget& is sufficient
class Widget; // forward declaration
void process(Widget *w); // pointer: forward decl is enough
// When forward declaration is sufficient:
// - Pointer or reference parameter: Widget*, Widget&
// - Return type as pointer: Widget*
// - Base class declared elsewhere (but defined in .cpp)
// When full include is required:
// - Inheriting from Widget: class MyWidget : public Widget
// - Accessing Widget members: w.field, w.method()
// - Creating Widget instances: Widget w;
// - Sizeof(Widget)
// - Template instantiation: std::vector<Widget>cpp
// IWYU-friendly header
#pragma once
class Widget; // forward declare (saves downstream compilation)
class Container {
Widget *head_; // pointer: forward decl is enough
public:
void add(Widget *w);
Widget *get(int idx);
};
// Container.cpp includes "widget.h" — only .cpp pays the compile cost6. Mapping files for third-party headers
6. 第三方头文件的映射文件
IWYU mapping files teach IWYU about indirect includes (where is provided by some internal STL header):
#include <vector>python
undefinedIWYU映射文件用于告知IWYU间接包含的情况(例如某个内部STL头文件提供了):
#include <vector>python
undefinediwyu.imp — IWYU mapping file
iwyu.imp — IWYU mapping file
[
Map internal LLVM headers to public ones
{ "include": ["<llvm/ADT/StringRef.h>", "private",
"<llvm/ADT/StringRef.h>", "public"] },
Map system headers to POSIX equivalents
{ "include": ["<bits/types.h>", "private", "<sys/types.h>", "public"] },
{ "include": ["<bits/socket.h>", "private", "<sys/socket.h>", "public"] },
Symbol → header mappings
{ "symbol": ["std::string", "private", "<string>", "public"] },
{ "symbol": ["NULL", "private", "<cstddef>", "public"] },
]
```bash[
Map internal LLVM headers to public ones
{ "include": ["<llvm/ADT/StringRef.h>", "private",
"<llvm/ADT/StringRef.h>", "public"] },
Map system headers to POSIX equivalents
{ "include": ["<bits/types.h>", "private", "<sys/types.h>", "public"] },
{ "include": ["<bits/socket.h>", "private", "<sys/socket.h>", "public"] },
Symbol → header mappings
{ "symbol": ["std::string", "private", "<string>", "public"] },
{ "symbol": ["NULL", "private", "<cstddef>", "public"] },
]
```bashUse mapping file
Use mapping file
iwyu -Xiwyu --mapping_file=iwyu.imp main.cpp
iwyu -Xiwyu --mapping_file=iwyu.imp main.cpp
IWYU ships with common mappings
IWYU ships with common mappings
ls /usr/share/include-what-you-use/
ls /usr/share/include-what-you-use/
gcc.stl.headers.imp, boost-1.62.imp, libcxx.imp, etc.
gcc.stl.headers.imp, boost-1.62.imp, libcxx.imp, etc.
iwyu -Xiwyu --mapping_file=/usr/share/include-what-you-use/gcc.stl.headers.imp
undefinediwyu -Xiwyu --mapping_file=/usr/share/include-what-you-use/gcc.stl.headers.imp
undefined7. What IWYU does not do
7. IWYU的局限性
IWYU has limits — be aware:
bash
undefinedIWYU存在一些限制,需要注意:
bash
undefinedIWYU may give wrong advice for:
IWYU may give wrong advice for:
- Macros from headers (hard to track)
- Macros from headers (hard to track)
- Template specializations in included headers
- Template specializations in included headers
- Headers required for correct ODR linking
- Headers required for correct ODR linking
Safe iterative workflow:
Safe iterative workflow:
1. Run IWYU
1. Run IWYU
2. Apply fixes with fix_include
2. Apply fixes with fix_include
3. Rebuild and run tests
3. Rebuild and run tests
4. Revert any changes that break the build
4. Revert any changes that break the build
5. Repeat until clean
5. Repeat until clean
Check for compilation cascade: how many TUs include a header
Check for compilation cascade: how many TUs include a header
grep -rl '#include "expensive.h"' src/ | wc -l
undefinedgrep -rl '#include "expensive.h"' src/ | wc -l
undefinedRelated skills
相关技能
- Use for ccache and other compile speed techniques
skills/build-systems/build-acceleration - Use for CMake integration of build analysis tools
skills/build-systems/cmake - Use for C++20 modules as a long-term solution to include bloat
skills/compilers/cpp-modules
- 使用了解ccache及其他编译加速技术
skills/build-systems/build-acceleration - 使用了解在CMake中集成构建分析工具的方法
skills/build-systems/cmake - 使用了解C++20模块作为解决头文件冗余的长期方案
skills/compilers/cpp-modules