[分享] Include What You Use
最近用了 include-what-you-use 這個工具,分享一下
https://yodalee.me/2020/10/2020_iwyu/
大家都知道,程式不是寫完就算了,是會長大跟更新
這時候 include 就會慢慢過時,可能本來需要的 include 現在不需要了
但通常在改程式碼時不會意識到這點
如果參考 Google 的 cpp coding guide,會看到 Include What You Use 這條準則:
If a source or header file refers to a symbol defined elsewhere, the file
should directly include a header file which properly intends to provide a
declaration or definition of that symbol. It should not include header files
for any other reason.
原始碼檔案和標頭檔所需的符號,都應該引入適當的標頭檔來提供宣告或定義;
不能因為其他理由而引入標頭檔。
Do not rely on transitive inclusions. This allows people to remove
no-longer-needed #include statements from their headers without breaking
clients. This also applies to related headers - foo.cc should include bar.h
if it uses a symbol from it even if foo.h includes bar.h.
不可依賴過渡引入。開發者可以隨時移除不需要的引入,又不會破壞客戶端的相依性;
這也適用於相關的標頭檔:即使 foo.h 已經引入 bar.h,foo.cc 還是要引入 bar.h 。
----
想當然爾,動輒幾百幾千個原始碼檔和標頭檔
怎麼可能一個一個去分析 include 有沒有寫對?
這就是這篇文章要介紹的工具了,名稱也非常直覺
就叫做 include what you use 簡稱 iwyu。
https://include-what-you-use.org/
iwyu 是專門開發來對付這個問題的
它執行起來就像一個 gcc,會去分析原始碼中所需的符號,並解析 include 檔案
確定符號都是直接引入而不是過渡引入;同時還會幫忙產生修正檔
一次完成引入的修正,簡直是 include 的殺手級工具。
----
iwyu 如果照文件的建議,是儘量搭配專案本來就有的 Makefile 或 CMake 使用
直接把 CC 或 CXX 代換成 include-what-you-use 加上 -k 編譯
iwyu 就會輸出編譯檔案 include 的修正檔了
(加上 -k 是因為 iwyu 回報 include 錯誤會導致編譯停止);
使用 iwyu 時一定要讓參數和真正編譯時儘量相同
才能分析編譯時使用的標頭檔和 -D 引入的巨集。
也有人會這樣跑:
find . -name "*.h" | xargs include-what-you-use <flags>
find . -name "*.c" | xargs include-what-you-use <flags>
但要注意,直接對著 .h 使用 iwyu 可能會有問題
如果 .h 是公開有人使用的話,套用修正可能會把這個標頭拆散
要使用者引入其他的標頭檔,這會破壞使用者的相依性,
特別是在大公司裡面其他你管不到的專案可能會用你管的函式庫,此時請小心使用。
----
依照 iwyu 文件的建議,使用 iwyu 所附的 fix_includes.py 套用修正:
make -k 2> iwyu.out
python fix_includes.py < iwyu.out
如此一來就完成 include 的修正。
雖然說我用完之後還是會遇到一些問題啦,像是出現這樣的 include
#include<data.h>
#include"data.h"
或是還是有些原始碼檔案缺了一些符號必須自己手動補上 include
但整體來說已經比自己手動修正快上不少了
--
______ |\
/ \ | \
/ ● ● \ |__\
/ ______ \ |
/ \__/ \___|
/______________\ |
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 220.134.248.249 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1604114190.A.1F0.html
推
10/31 15:33,
3年前
, 1F
10/31 15:33, 1F
推
10/31 16:06,
3年前
, 2F
10/31 16:06, 2F
推
11/01 15:09,
3年前
, 3F
11/01 15:09, 3F
→
11/01 15:46,
3年前
, 4F
11/01 15:46, 4F
→
11/01 15:46,
3年前
, 5F
11/01 15:46, 5F
→
11/01 15:46,
3年前
, 6F
11/01 15:46, 6F
→
11/01 15:46,
3年前
, 7F
11/01 15:46, 7F
→
11/01 15:46,
3年前
, 8F
11/01 15:46, 8F
→
11/01 15:46,
3年前
, 9F
11/01 15:46, 9F
問題不是這樣的,假設你今天刪了幾行 code,裡面有一行用到某個資料結構
像是 struct smartdata 好了,而且這是最後一個用到 smartdata 的地方
理論上,應該要去 include 的地方,把 #include<smartdata.h> 刪掉
問題是有多少人會注意到這件事?就連 code review 都不一定會注意到了
又或者專案把 a.h 拆分成 a1.h a2.h 然後 a.h 裡面 include a1.h/a2.h
其他專案會記得把所有 a.h 換成 a1.h 或 a2.h 嗎?
coding standard 是目標,但無論多少教育/訓練,在實行上就是會有疏失
"因為人就是會犯錯,所以在鉛筆的後面會有橡皮擦"
工具是用來輔助人,抓出人犯錯的地方,而不是說人就不用教育/訓練
※ 編輯: lc85301 (220.134.248.249 臺灣), 11/01/2020 17:16:48
→
11/01 19:19,
3年前
, 10F
11/01 19:19, 10F
→
11/01 19:23,
3年前
, 11F
11/01 19:23, 11F
→
11/01 19:29,
3年前
, 12F
11/01 19:29, 12F
→
11/01 19:53,
3年前
, 13F
11/01 19:53, 13F
→
11/01 20:06,
3年前
, 14F
11/01 20:06, 14F
→
11/01 20:06,
3年前
, 15F
11/01 20:06, 15F
→
11/01 20:06,
3年前
, 16F
11/01 20:06, 16F
→
11/01 20:06,
3年前
, 17F
11/01 20:06, 17F
→
11/01 20:06,
3年前
, 18F
11/01 20:06, 18F
→
11/01 20:34,
3年前
, 19F
11/01 20:34, 19F
→
11/01 20:34,
3年前
, 20F
11/01 20:34, 20F
推
11/01 23:14,
3年前
, 21F
11/01 23:14, 21F
→
11/01 23:14,
3年前
, 22F
11/01 23:14, 22F
→
11/01 23:14,
3年前
, 23F
11/01 23:14, 23F
→
11/01 23:15,
3年前
, 24F
11/01 23:15, 24F
推
11/02 10:03,
3年前
, 25F
11/02 10:03, 25F
→
11/02 11:13,
3年前
, 26F
11/02 11:13, 26F
推
11/04 10:09,
3年前
, 27F
11/04 10:09, 27F
→
11/04 11:26,
3年前
, 28F
11/04 11:26, 28F
→
11/04 11:26,
3年前
, 29F
11/04 11:26, 29F
→
11/04 11:27,
3年前
, 30F
11/04 11:27, 30F
→
11/04 11:27,
3年前
, 31F
11/04 11:27, 31F
推
11/04 11:33,
3年前
, 32F
11/04 11:33, 32F
→
11/04 11:34,
3年前
, 33F
11/04 11:34, 33F
→
11/04 11:36,
3年前
, 34F
11/04 11:36, 34F
推
11/04 12:48,
3年前
, 35F
11/04 12:48, 35F
→
11/04 12:50,
3年前
, 36F
11/04 12:50, 36F
→
11/04 12:50,
3年前
, 37F
11/04 12:50, 37F
推
11/04 12:53,
3年前
, 38F
11/04 12:53, 38F
→
11/04 12:58,
3年前
, 39F
11/04 12:58, 39F
→
11/05 16:04,
3年前
, 40F
11/05 16:04, 40F
→
11/05 16:04,
3年前
, 41F
11/05 16:04, 41F
推
11/05 16:46,
3年前
, 42F
11/05 16:46, 42F
推
11/05 16:51,
3年前
, 43F
11/05 16:51, 43F
→
11/05 16:52,
3年前
, 44F
11/05 16:52, 44F
→
11/05 18:55,
3年前
, 45F
11/05 18:55, 45F
→
11/06 09:07,
3年前
, 46F
11/06 09:07, 46F
→
11/06 09:09,
3年前
, 47F
11/06 09:09, 47F
→
11/06 09:11,
3年前
, 48F
11/06 09:11, 48F
推
11/06 10:13,
3年前
, 49F
11/06 10:13, 49F
→
11/06 10:19,
3年前
, 50F
11/06 10:19, 50F
推
11/06 10:37,
3年前
, 51F
11/06 10:37, 51F
→
11/06 12:41,
3年前
, 52F
11/06 12:41, 52F
→
11/06 12:51,
3年前
, 53F
11/06 12:51, 53F
推
11/06 12:51,
3年前
, 54F
11/06 12:51, 54F
→
11/06 12:53,
3年前
, 55F
11/06 12:53, 55F
推
11/06 13:01,
3年前
, 56F
11/06 13:01, 56F
→
11/06 13:02,
3年前
, 57F
11/06 13:02, 57F
→
11/06 13:03,
3年前
, 58F
11/06 13:03, 58F
→
11/06 13:03,
3年前
, 59F
11/06 13:03, 59F
→
11/06 13:04,
3年前
, 60F
11/06 13:04, 60F
→
11/06 13:04,
3年前
, 61F
11/06 13:04, 61F
→
11/06 13:05,
3年前
, 62F
11/06 13:05, 62F
推
11/06 13:11,
3年前
, 63F
11/06 13:11, 63F
推
11/06 13:15,
3年前
, 64F
11/06 13:15, 64F
→
11/06 13:15,
3年前
, 65F
11/06 13:15, 65F
→
11/06 13:15,
3年前
, 66F
11/06 13:15, 66F
→
11/06 13:15,
3年前
, 67F
11/06 13:15, 67F
推
11/06 13:20,
3年前
, 68F
11/06 13:20, 68F
→
11/06 13:20,
3年前
, 69F
11/06 13:20, 69F
→
11/06 13:21,
3年前
, 70F
11/06 13:21, 70F
→
11/06 13:22,
3年前
, 71F
11/06 13:22, 71F
→
11/06 13:22,
3年前
, 72F
11/06 13:22, 72F
推
11/06 13:24,
3年前
, 73F
11/06 13:24, 73F
→
11/06 13:24,
3年前
, 74F
11/06 13:24, 74F
推
11/06 13:28,
3年前
, 75F
11/06 13:28, 75F
→
11/06 13:28,
3年前
, 76F
11/06 13:28, 76F
→
11/06 13:28,
3年前
, 77F
11/06 13:28, 77F
→
11/06 13:29,
3年前
, 78F
11/06 13:29, 78F
推
11/06 15:00,
3年前
, 79F
11/06 15:00, 79F
推
11/06 16:20,
3年前
, 80F
11/06 16:20, 80F
→
11/06 18:06,
3年前
, 81F
11/06 18:06, 81F