include-what-you-use

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Include What You Use (IWYU)

Include What You Use (IWYU)

Purpose

用途

Guide agents through using IWYU to reduce unnecessary
#include
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.
指导开发者使用IWYU减少不必要的
#include
指令,解读IWYU报告和映射文件,选择前向声明还是完整头文件包含,并将IWYU集成到CMake构建流程中,以减少大型代码库中的编译连锁反应。

Triggers

触发场景

  • "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
undefined
bash
undefined

Install

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
undefined
iwyu_tool.py -p build/ 2>&1 | tee iwyu.log
undefined

2. CMake integration

2. CMake集成

cmake
undefined
cmake
undefined

CMakeLists.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()

```bash
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()

```bash

Build with IWYU analysis

Build with IWYU analysis

cmake -S . -B build -DCMAKE_CXX_COMPILER=clang++ cmake --build build 2>&1 | tee iwyu.log
undefined
cmake -S . -B build -DCMAKE_CXX_COMPILER=clang++ cmake --build build 2>&1 | tee iwyu.log
undefined

3. 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
undefined
bash
undefined

fix_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
undefined
iwyu_tool.py -p build/ 2>&1 | fix_include
undefined

5. 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 cost

6. Mapping files for third-party headers

6. 第三方头文件的映射文件

IWYU mapping files teach IWYU about indirect includes (where
#include <vector>
is provided by some internal STL header):
python
undefined
IWYU映射文件用于告知IWYU间接包含的情况(例如某个内部STL头文件提供了
#include <vector>
):
python
undefined

iwyu.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"] }, ]

```bash

Use 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
undefined
iwyu -Xiwyu --mapping_file=/usr/share/include-what-you-use/gcc.stl.headers.imp
undefined

7. What IWYU does not do

7. IWYU的局限性

IWYU has limits — be aware:
bash
undefined
IWYU存在一些限制,需要注意:
bash
undefined

IWYU 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
undefined
grep -rl '#include "expensive.h"' src/ | wc -l
undefined

Related skills

相关技能

  • Use
    skills/build-systems/build-acceleration
    for ccache and other compile speed techniques
  • Use
    skills/build-systems/cmake
    for CMake integration of build analysis tools
  • Use
    skills/compilers/cpp-modules
    for C++20 modules as a long-term solution to include bloat
  • 使用
    skills/build-systems/build-acceleration
    了解ccache及其他编译加速技术
  • 使用
    skills/build-systems/cmake
    了解在CMake中集成构建分析工具的方法
  • 使用
    skills/compilers/cpp-modules
    了解C++20模块作为解决头文件冗余的长期方案