C++中include-what-you-use(iwyu)去除多餘標頭檔案工具開發文件
開篇敬知乎大神~
大神首頁
作業系統: Windows
所需工具: SVN、CMake、visual studio 2015以上版本、Sublime Text 3
操作步驟:
1.新建llvm資料夾,使用svn將llvm官方原始碼匯出到該資料夾
2.在llvm/tools下新建clang資料夾,使用svn將clang官方原始碼匯出到該資料夾
3.到此,已準備好了所需的原始碼,開始使用CMake生成專案檔案
3.1新建llvm-build資料夾(不能在llvm資料夾底下),用於存放CMake生成的專案檔案 3.2 [可選]為了減少CMake匯出量,可作以下配置(以cmake-gui為例) a. CMake裡先將所有的打勾都取消 b.將所有的all改成host,意思是隻針對本平臺進行配置 c.給下面的選項打勾 LLVM_INCLUDE_TOOLS LLVM_INCLUDE_UTILS LLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD本項含義是: 編譯llvm\tools\clang\tools\extra下的專案 d.將所有的MD換為MT,將MDd換為MTd 3.3使用CMake匯出vs專案檔案 PS:Cmake這個專案不是必需的,但的確可以大大方便生成專案檔案,我遇到了一個問題就是Cmake不好用 我的方法是:使用cmd命令列來生成專案檔案,在命令列輸入: C:\project\llvm-build>cmake–G ”Visual Studio 15 2017” ../llvm –Thost=x64
4.使用VS開啟llvm-build/llvm.sln,選中clang專案然後生成(約1小時)。
5.將iwyu專案新增到clang專案中,一般是複製到llvm\tools\clang\tools資料夾下,這個要看iwyu的文件
6.使用Sublime Text 3編輯llvm/tools/clang/tools/CMakeLists.txt,在裡面新增
add_subdirectory(include-what-you-use)
7.使用Cmake重新生成專案檔案。
8.在VS中提示發生更改,重新載入一下即可。
9.在VS中生成include-what-you-use
PS:生成的時候遇見了兩個小警告(TemplateSpecializationType::PrintTemplateArgumentList和TemplateSpecializationType:: TemplateArgumentListInfo),應該和列印引數有關,註釋掉就OK了。
專案測試:
例項1:
建立
a.h
b.h
c.h
ttt.cpp
在命令列輸入命令:
C:\project\llvm-build\bin\Debug\include-what-you-use.exe-x c++ -std=c++11 -Xiwyu –verbose=2 -Xiwyu –transitive_includes_only ttt.cpp2> iwyu.out
輸出的結果將被重定向到iwyu.out檔案中
例項2:
在命令列輸入命令:
C:\project\llvm-build\bin\Debug\include-what-you-use.exe-x c++ -std=c++11 -Xiwyu –verbose=2 -Xiwyu –transitive_includes_only foo.cpp2> iwyu.out
輸出的結果將被重定向到iwyu.out檔案中
其實,在網路中查詢此開發工具過程中,發現iwyu更適合在Linux系統工作,Windows系統大大增加了編譯的難度,include-what-you-use(等下直接簡稱為iwyu)的確是一個很有用的工具,可以自動刪除不必要的#include並能生成前置宣告,雖然較難上手,但一旦建立起自動化處理機制後,可以很方便的清理專案的c++檔案中多餘的#include。
但iwyu的主要不足是:去除標頭檔案中多餘的#include不夠徹底,或者說,可以很徹底,但大部分情況下將會導致其他的檔案發生編譯錯誤。
通過跟蹤其原始碼實現流程以及結合使用的情況來看,iwyu對於c++檔案的清理僅依賴於通過單個檔案的解析,並沒能分析出整個專案的依賴圖。這也決定了iwyu的主要使用場景是清理.cpp檔案,而非.h檔案,因為這樣更安全。
舉一個例子:
假設有all.h,裡面有包含2個有用的標頭檔案,3個沒用的標頭檔案
all.h包括#include “a.h”#include “b.h” #include “永遠用不到的標頭檔案1.h” #include “永遠用不到的標頭檔案2.h”#include “永遠用不到的標頭檔案3.h”class C{};
現在,假設專案中的A.cpp和B.cpp均包含了all.h,其中,A.cpp僅使用了"a.h"內的內容,而B.cpp僅使用了"b.h"的內容。
此時使用iwyu處理A.cpp和B.cpp,A.cpp中的#include"all.h"將被替換為#include "a.h",B.cpp中的將被替換為#include "b.h",而all.h內容並不會改動。
但我們還是希望all.h中多餘的3個檔案能被清理掉的,於是我們繼續使用iwyu清理all.h,但很明顯iwyu是不知道a.h和b.h是曾經被使用到的,於是all.h最後將變成
all.h
class C{};
all.h中所有的#include,包括#include”a.h”和#include “b.h”都被刪掉了,於是專案將發生編譯錯誤。
這個問題挺難避免的,比較折中的做法是隻清理cpp檔案,再根據需求自行清理h檔案。但相應的清理效果就可能會大打折扣了。因為說不定就是某些無用的h檔案被大量cpp檔案包含才導致專案編譯速度變慢的,而我們又不方便直接定位到這些#include。
所以生成專案中的各個檔案的依賴關係結構是很有必要的,iwyu在這方面仍然不足,所以我覺得還是可以把工具發出來作為備用。
而對於linux下的c++專案,由於iwyu已經做得足夠強大,Windows系統大大增加了編譯的難度。