web-dev-qa-db-ja.com

C / C ++で余分な#includeを検出しますか?

ファイルのヘッダーセクションは常に大きくなりますが、決して小さくなることはありません。ソースファイルの寿命を通じて、クラスは移動され、リファクタリングされた可能性があります。また、必要のない#includesがかなり存在する可能性があります。そのままにしておくと、コンパイル時間が長くなり、不要なコンパイルの依存関係が追加されます。まだ必要なものを把握しようとするのは非常に退屈です。

余分な#includeディレクティブを検出し、安全に削除できるものを提案できるツールがありますか?
糸くずは多分これをしますか?

267
shoosh

自動ではありませんが、 doxygen#includedファイルの依存関係図を生成します。それらを視覚的に確認する必要がありますが、何が何を使用しているのかを把握するのに非常に役立ちます。

40
anon

Googleのcppclean(リンク: downloaddocumentation )は、C++の問題のいくつかのカテゴリを見つけることができ、余分な#includeを見つけることができます。

これを行うことができるClangベースのツール include-what-you-use もあります。 include-what-you-useは前方宣言を提案することもできるので(#includeをそれほど必要としない)、オプションで#includesをクリーンアップできます。

Eclipse CDT の現在のバージョンにもこの機能が組み込まれています:[ソース]メニューから[インクルードの整理]をクリックすると、#includeがアルファベット順になり、Eclipseが直接使用せずに使用していると考えるヘッダーが追加されます。必要ないと思われるヘッダーをコメント化します。ただし、この機能は100%信頼できるものではありません。

160
Josh Kelley

同様の問題を解決する include-what-you-use も確認してください。

58
Tzafrir

不要なインクルードの検出に関する問題は、単なる型依存性チェッカーになれないことです。余分なインクルードとは、コンパイルに価値のないものを提供するファイルですおよびは、他のファイルが依存する別のアイテムを変更しません。ヘッダーファイルがコンパイルを変更する方法は多数あります。たとえば、定数の定義、使用済みマクロの再定義および/または削除、名前のルックアップを何らかの方法で変更する名前空間の追加などです。名前空間のようなアイテムを検出するためには、プリプロセッサよりもはるかに多くのものが必要です。実際、ほとんどの場合、完全なコンパイラが必要です。

Lintはよりスタイルチェッカーであり、確かにこの完全な機能はありません。

余分なインクルードを検出する唯一の方法は、スイートを削除、コンパイル、実行することだと思います。

24
JaredPar

PCLint がこれを行うと思いましたが、それを見てから数年が経ちました。あなたはそれをチェックアウトするかもしれません。

このブログ を見て、著者は未使用のインクルードを見つけるためのPCLintの設定について少し話しました。一見の価値があるかもしれません。

15
itsmatt

CScout リファクタリングブラウザーは、C(残念ながらC++ではありません)コードの余分なincludeディレクティブを検出できます。どのように機能するかの説明は this ジャーナル記事にあります。

7

単一の#includeディレクティブを消去し、プロジェクトをコンパイルし、コンパイルエラーが発生しなかった場合に名前を#includeおよび削除されたファイルに記録するクイックスクリプトを作成できます。

夜間に実行すると、翌日には削除できるインクルードファイルの100%正しいリストが表示されます。

時にはブルートフォースが機能するだけです:-)


編集:そして時々そうではありません:-)。コメントからの少しの情報はここにあります:

  1. 2つのヘッダーファイルを個別に削除できますが、両方を同時に削除することはできません。解決策は、実行中にヘッダーファイルを削除し、それらを戻さないことです。これにより、安全に削除できるファイルのリストが見つかりますが、このアルゴリズムでは検出できないファイルを削除するソリューションが存在する場合があります。 (削除するインクルードファイルのスペースを貪欲に検索します。ローカルの最大値のみを検索します)
  2. いくつかのマクロが#ifdefに応じて異なる方法で再定義されている場合、動作に微妙な変化があるかもしれません。これらは非常にまれなケースであり、ビルドの一部である単体テストがこれらの変更をキャッチするはずです。
6
Gilad Naor

あなたが求めていることを達成するための本格的なツールを見つけたことがありません。私が使用した最も近いものは IncludeManager です。これにより、ヘッダーインクルージョンツリーがグラフ化されるため、1つのファイルのみに含まれるヘッダーや循環ヘッダーインクルージョンを視覚的に見つけることができます。

5
Dan Olson

ここに投稿してすみません(再投稿)。多くの場合、コメントを展開しません。

Crashmstrへのコメントを確認してください。FlexeLint/ PC-Lintがこれを行います。情報メッセージ766。これについては、マニュアル(バージョン8.0)のセクション11.8.1で説明しています。

また、これは重要です。メッセージが消えるまで繰り返してください。つまり、未使用のヘッダーを削除した後、lintを再実行すると、不要なヘッダーを削除すると、より多くのヘッダーファイルが「不要」になっている可能性があります。 (それは愚かに聞こえるかもしれませんが、ゆっくり読んで解析してください、それは理にかなっています。)

5
Dan

Eclipse CDTを使用している場合、 http://includator.com を試すことができます。これは(この記事の執筆時点で)ベータテスターに​​無料で、不要な#includeを自動的に削除するか、欠落しているものを追加します。 FlexeLintまたはPC-Lintを使用しており、Elicpse CDTを使用しているユーザーの場合、 http://linticator.com がオプションになる可能性があります(ベータテストも無料)。 Lintの分析を使用しながら、余分な#includeステートメントを自動的に削除するためのクイックフィックスを提供します。

4
PeterSom

Flexelint(PC-LintのUNIXバージョン)を使用してみましたが、結果は多少異なります。これは、私が非常に大きくて節のあるコードベースで作業しているためです。未使用として報告された各ファイルを注意深く調べることをお勧めします。

主な心配は誤検知です。同じヘッダーの複数のインクルードは、不要なヘッダーとして報告されます。 Flexelintは、ヘッダーが含まれる行やヘッダーが以前に含まれていた場所を通知しないため、これは悪いことです。

自動化ツールがこれを誤る可能性のある方法の1つ:

A.hppで:

class A { 
  // ...
};

B.hppの場合:

#include "A.hpp

class B {
    public:
        A foo;
};

C.cppの場合:

#include "C.hpp"  

#include "B.hpp"  // <-- Unneeded, but lint reports it as needed
#include "A.hpp"  // <-- Needed, but lint reports it as unneeded

Flexelintからのメッセージを盲目的にたどると、#include依存関係が台無しになります。より多くの病理学的なケースがありますが、基本的には、最良の結果を得るためにヘッダーを自分で調べる必要があります。

ブログGames内の Physical Structure and C++ に関するこの記事を強くお勧めします。彼らは、#include混乱をクリーンアップするための包括的なアプローチを推奨しています。

ガイドライン

これは、ファイル間の物理的な依存関係の数を最小限に抑えるためのLakosの本からのガイドラインの抜粋です。私は何年もそれらを使用してきましたが、私はいつも結果に本当に満足しています。

  1. すべてのcppファイルには、最初に独自のヘッダーファイルが含まれています。 [をちょきちょきと切る]
  2. ヘッダーファイルには、解析に必要なすべてのヘッダーファイルが含まれている必要があります。 [をちょきちょきと切る]
  3. ヘッダーファイルには、解析に必要な最小限のヘッダーファイルが必要です。 [をちょきちょきと切る]
3
Ben Martin

この議論を終了するために、c ++プリプロセッサは完全に調整されています。インクルードが不要かどうかは、セマンティックプロパティです。したがって、Riceの定理から、インクルードが不要であるかどうかは決定できません。インクルードが不要かどうかを(常に正しく)検出するプログラムはありません。

2
Algoman

Visual Studioに統合できる無料のツール File Dependencies Watcher があります。余分な#includeが赤で表示されます。

2
Vladimir

この記事 は、Doxygenの解析を使用して#includeを削除する手法を説明しています。これは単なるPerlスクリプトなので、非常に使いやすいです。

2
Steve Gury

これは単純な 余分なヘッダーを識別する強引な方法が含まれています です。完全ではありませんが、「明らかな」不要なインクルードを排除します。これらを取り除くことは、コードのクリーンアップに大いに役立ちます。

scripts はGitHubから直接アクセスできます。

1
ap-osd

少し遅れるかもしれませんが、私はかつてあなたが望んでいたことをしたWebKit Perlスクリプトを見つけました。私は信じるいくつかの適応を必要とします(私はPerlに精通していません)が、トリックを行う必要があります:

http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(これはトランクにファイルがないため古いブランチです)

1
rubenvb

余分な#includeファイルには2つのタイプがあります。

  1. 実際にはモジュール(.c、.cpp)にまったく必要のないヘッダーファイル
  2. ヘッダーファイルはモジュールに必要ですが、複数回、直接、または間接的にインクルードされます。

私の経験では、それを検出するのにうまく機能する2つの方法があります。

  • gcc -Hまたはcl.exe/showincludes(問題2を解決)

    実際には、すべてのMakefileがCFLAGSオプションをオーバーライドしない場合、makeの前にCFLAGS = -Hをエクスポートできます。または、使用したとおり、cc/g ++ラッパーを作成して、$(CC)および$(CXX)の各呼び出しに-Hオプションを強制的に追加できます。ラッパーのディレクトリを$ PATH変数の先頭に追加すると、makeはすべて代わりにwrapperコマンドを使用します。もちろん、ラッパーは実際のgccコンパイラーを呼び出す必要があります。 Makefileがgccを直接使用する場合、このトリックを変更する必要があります。 $(CC)または$(CXX)の代わりに、または暗黙のルールにより。

    コマンドラインで微調整することにより、単一のファイルをコンパイルすることもできます。ただし、プロジェクト全体のヘッダーを削除する場合。次の方法ですべての出力をキャプチャできます。

    きれいにする

    2>&1を作成| tee result.txt

  • PC-Lint/FlexeLint(1と2の両方の問題を解決)

    必ず+ e766オプションを追加してください。この警告は、未使用のヘッダーファイルに関するものです。

    pclint/flint -vf ...

    これにより、pclint出力にはヘッダーファイルが含まれ、ネストされたヘッダーファイルは適切にインデントされます。

1
zhaorufei

CLion 、JetBrainsのC/C++ IDEは、冗長インクルードをすぐに検出します。これらはエディターではグレー表示されていますが、 現在のファイルまたはプロジェクト全体にインクルードを最適化する の機能もあります。

ただし、この機能に対して料金を支払うことがわかりました。 CLionは、最初にロードされたときにプロジェクトをスキャンして分析するのに時間がかかります。

1
congusbongus

Gimpel Softwareの PC Lint は、インクルードファイルがコンパイルユニットに複数回インクルードされたときにレポートできます。、しかし、あなたが探している方法で必要ではないインクルードファイルを見つけることができません。

編集: できる。 itsmattの答え を参照

0
crashmstr