Include-what-you-use工具介绍
简介
Include-what-you-use
工具(以下简称iwyu)是Google推出,基于Clang的C/C++工程冗余头文件检查工具。iwyu依赖Clang
编译套件,因此,针对每个Clang
版本,会有对应的iwyu
工程分支。
使用该工具的好处
- 更快的编译。当cpp文件包含冗余头文件时,编译器会读取、预处理和解析更多的代码,如果有模板存在,则会引入更多的代码,这会加大编译构建时间。
- 更好的重构。假如你准备重构
foo.h
,使得它不再使用vector
,你很可能会从foo.h
文件中移除#include<vector>
。理论上可以这么做,但实际上不行,因为其他文件可能会通过foo.h
来间接引用vector
,贸然移除会造成其他文件编译失败。iwyu工具可以找到并去掉这种间接引用。 - 头文件自注释。通过查看必须头文件注释,可知道该功能依赖于其他哪些子功能。
- 使用前向声明代替
include
语句,减少依赖,减少可执行程序大小
Windows平台下使用
在Window
平台上,使用如下版本:
clang_8.0
iwyu 0.12
Visual Studio 2017
使用预编译LLVM来构建
下载并安装LLVM-8.0.0
二进制安装包,安装在D:\Program Files\LLVM
下,使用如下语句来构建:
cd iwyu/build cmake -G "Visual Studio 15 2017" Win64 -DCMAKE_PREFIX_PATH=D:\Program Files\LLVM ../include-what-you-use/
提示如下错误:
由于二进制安装包不包含iwyu
构建cmake
所需的查找文件LLVMConfig.cmake
,导致构建失败,不采用这种方式来构建。
参考链接:Embeding LLVM in your project
备注:后来发现,通过编译llvm
源码,可以从源码中的LLVMConfig.cmake.in
生成对应的LLVMConfig.cmake
文件,那这样还不如直接使用源码来构建。
使用源码来构建
下载iwyu 0.12
版本,此版本依赖clang_8.0
版本,在llvm官网上,下载LLVM 8.0.0
版本的llvm
和Clang
源码。按照如下顺序来存放:
- 新建
llvm
目录以及同级别的llvm-build
目录 - 将
llvm_8.0
源码解压到llvm
目录中 - 在
llvm/tools/
目录下新建Clang
目录,将Clang
源码在此目录解压 - 将
iwyu 0.12
源码复制到llvm/tools/clang/tools/
目录 - 编辑
llvm/tools/clang/tools/CMakeLists.txt
,增加以下一句话add_clang_subdirectory(include-what-you-use-clang_8.0)
最后形成的目录结构如下:
llvm-build llvm -- tools ---- clang ------tools --------include-what-you-use-clang_8.0
源码目录结构准备好,通过cmake-gui来进行配置。
备注:在构建时,要选择Win64版本,如果选择Win32来构建,会出现fatal error C1060: 编译器的堆空间不足
的问题,经过查找资料,是32位cl.exe编译器使用超过3.5G内存时会报错。
构建完成后,进行如下调整:
- 去掉所有的打勾,只保留以下四项打勾:
- LLVM_ENABLE_IDE
- LLVM_INCLUDE_TOOLS
- LLVM_INCLUDE_UTILS
- LLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD
- 将LLVM_DYLIB_COMPONENTS由all改为host、将LLVM_TARGETS_TO_BUILD由all改为host。减少构建工程输出
配置完成后重新生成和构建,打开LLVM.sln
工程,直接生成Include-what-you-use
工程,缺少哪些库,就编译哪些库。
构建结果如下:
由于该工具基于Clang
,因此,在使用时有两部分选项:
- iwyu选项,需要添加
-Xiwyu
前缀来明确指出 - clang选项。例如,如果需要支持c++11,需要添加
-x c++
表示编译的是c++类型文件-std=c++11
表示按c++11规范来编译
备注:使用clang的c++11标准来编译,在使用auto关键字时,会提示
error: ‘auto‘ return without trailing return type; deduced return types are a C++14 extension
相关问题链接在此。clang建议使用c++14类型,或者使用 -> decltype 来声明返回类型。
如果不明确指出,可以忽略clang的选项。
使用方法如下:
.\include-what-you-use.exe -Xiwyu -transitive_includes_only XXX.cpp
Linux平台下使用
在Linux平台下的构建流程简单直接。
- 安装
Clang
,查看Clang
的版本
当前系统使用的Clang
版本为3.8. - 新建
iwyu
目录,下载对应Clang
版本的iwyu
源码,git clone -b clang_3.8 https://github.com/include-what-you-use/include-what-you-use.git
iwyu
依赖curses
库,如果没有安装,需要执行sudo apt-get install libncurses5-dev
来安装iwyu
依赖Clang
开发包,如果只是通过apt命令行安装Clang
,需要使用sudo apt-get install libclang-3.8-dev
来安装开发包
- 使用
cmake
源码外来构建iwyu
工具
- mkdir build && cd build
- cmake -G "Unix Makefiles" -DIWYU_LLVM_ROOT_PATH=/usr/lib/llvm-3.8 ../include-what-you-use
- make
- make install
构建过程中,出现如下错误:
经分析发现时本机未安装Clang
开发包,参照上面提到的来安装即可。
构建完成后,在当前目录下生成Include-what-you-use
工具,后续使用它即可。
测试
以一个简单c++程序来测试:使用./include-what-you-use simple_test.cpp
来进行静态分析,如果使用了C++11特性,则需要添加-std=c++11
#include <fcntl.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> #include <sys/user.h> #include <execinfo.h> int main(int argc, char* argv[]) { return 0; }
分析结果如下:
根据上述结果即可进行有针对性的头文件包含优化。
工程整合
使用cmake构建工具,直接支持iwyu
工具,配合iwyu
源码下的fix_includes.py
脚本工具,可进行自动化清理。
CMake 3.3版本引入目标新属性CXX_INCLUDE_WHAT_YOU_USE
,支持iwyu
工具。
使用方法如下:
cmake .. -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=$(which include-what-you-use) make 2> iwyu.out fix_includes.py -n --nosafe_headers --comments < iwyu.ou # 该命令输出准备删除的动作,去掉-n选项,会修改实际源文件。 --comments:在每个include中指出具体使用了哪些导出函数
可依据iwyu.out内容来手动移除,也可使用fix_includes.py
来进行自动化清理。
参考文档: