LoginSignup
43

More than 5 years have passed since last update.

include-what-you-useとjenkinsでC/C++プロジェクトから不要な#includeを洗い出す

Last updated at Posted at 2017-08-28

はじめに

include-what-you-useはC/C++のコードから不要な#includeを洗い出し、前方宣言への置き換えや削除を提案してくれるツールです。コードから不要な#includeが減るとコンパイル時間が短くなり、コードが読みやすくリファクタリングしやすくなります1。不要な#includeを減らすにはまず洗い出しが必要です。この作業はinclude-what-you-useを使うと簡単に済ませることができます。ここではinclude-what-you-useの導入方法とinclude-what-you-useの結果をJenkinsで集計する方法を紹介します。

インストール

ひとつのコードをinclude-what-you-useしてみる

まずはひとつのコードに対してinclude-what-you-useをしてみます。

$ include-what-you-use test.cpp

追加のインクルードパスが必要であれば -I オプションを利用てください。

$ include-what-you-use test.cpp -IhogeLibInclude -IfugaLibInclude

結果はこのようになります。

test.cpp should add these lines:
class Piyo;

test.cpp should remove these lines:
- #include "Fuga.h"  // lines 2-2
- #include "Piyo.h"  // lines 3-3

The full include-list for test.cpp:
#include "Hoge.h"  // for Hoge
class Piyo;
---

この例では#include "Piyo.h"は前方宣言に置き換え、#include "Fuga.h"は削除できることがinclude-what-you-wantにより指摘されています。

プロジェクトにinclude-what-you-useを実行する

プロジェクトがCMakeを利用している場合

いくつかやり方があります。

1. CMAKE_C(XX)_INCLUDE_WHAT_YOU_USEを利用する

cmake3.3以降で使える方法です。通常のコンパイルと並行してinclude-what-you-useします。cmakeするときにCMAKE_C(XX)_INCLUDE_WHAT_YOU_USE変数にinclude-what-you-useへのパスをセットします。

cmake . -DCMAKE_C_INCLUDE_WHAT_YOU_USE=path/to/include_what_you_use -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=path/to/include_what_you_use

2. CMAKE_C(XX)_COMPILERを利用する

コンパイラをinclude-what-you-useに置き換える方法です。cmakeするときにCMAKE_C(XX)_COMPILER変数にinclude-what-you-useへのパスをセットします。このときcmakeによるコンパイラの簡易チェックをパスするために、CMAKE_C(XX)_COMPILER_WORKSを1にセットしなければいけません。

cmake . -DCMAKE_C_COMPILER=path/to/include_what_you_use -DCMAKE_CXX_COMPILER=path/to/include_what_you_use -DCMAKE_C_COMPILER_WORKS=1 -DCMAKE_CXX_COMPILER_WORKS=1

CMake以外のビルドシステムを使っている場合

基本的にはコンパイラをinclude-what-you-useに置き換えればよいはずです。(やったことないので正直わかりません)

Jenkinsで集計する

include-what-you-useの結果はJenkins Warning Pluginで集計することができます。

Jenkins Warning Pluginにinclude-what-you-use用のパーサーを追加する

"Jenkinsの管理"->"システムの設定" を開き、"コンパイラの警告"にinclude-what-you-use用の設定をしていきます。"名前"、"リンク名"、"推移レポート名"にはなんでも良いのですがとりあえずinclude-what-you-useを入力してください。"正規表現"には次の内容を入力してください。

(.*) should (.*) these lines:$|^The full include-list for (.*)|(.*) // lines (.*)-(.*)$|(.+)

"マッピングスクリプト"には次のスクリプトを入力してください。

import hudson.plugins.warnings.parser.Warning
import hudson.plugins.analysis.util.model.Priority

public class Line{
    def public static String filename;
    def public static String category;
}

if (matcher.group(2) == "add" || matcher.group(2) == "remove"){
    Line.filename = matcher.group(1);
    Line.category = matcher.group(2);
    return;
}

if (matcher.group(3) != null){
    Line.filename = null;
    Line.category = null;
    return;
}

if(Line.category == "remove"){
    return new Warning(Line.filename, matcher.group(6).toInteger(), "iwyu", Line.category, Line.category + " " + matcher.group(4), Priority.HIGH)
}
else if(Line.category == "add"){
    return new Warning(Line.filename, 0, "iwyu", Line.category, Line.category + " " + matcher.group(7).replaceAll("<|>", ""), Priority.LOW)
}

return;

include-what-you-use用のジョブを作成する

  • Jenkinsにジョブを新規作成(フリースタイル・プロジェクトのビルド)し、ジョブ内でinclude-what-you-useで全ビルドかけるようなシェルスクリプト・バッチファイルを用意します。
  • ジョブの"設定"->"ビルド後の処理"に"コンパイラの警告の集計(scan for compiler warnings)"を追加します。
  • "コンパイラの警告の集計"の"パーサー"にinclude-what-you-useを指定します。
  • "コンパイラの警告の集計"の"常に実行"にチェックを入れます。

結果の扱い方

基本的にはinclude-what-you-useの提案通りにコードを修正していけばよいのですが例外があります。include-what-you-useは「他のヘッダファイルで宣言されたシンボル(型や関数、マクロなど)を利用するときは、それらが宣言されているヘッダファイルを直接#includeするべきだ」というポリシーを持っています。このポリシーと相容れないコードについては、include-what-you-useの提案を無視しなければいけません。例えばクライアントコードにおける#includeの数を減らすため、もしくはモジュール外に提供するシンボルを限定するために複数の#includeをまとめているヘッダファイルなどはinclude-what-you-useのポリシーに反するものです。(まとめヘッダファイルの#includeを削除し、まとめヘッダファイルが#includeしていた実際にシンボルが宣言されているヘッダファイルを#includeするように提案されてしまいます。)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43