簡介
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
來進行自動化清理。
參考文檔: