メイクファイルで指定された依存関係をツリーとして表示する方法は?


18

問題

メイクファイルの1つ以上のターゲットの依存関係を確認したい。そこで、メイクファイルを解析し、ツリーのような形式(インデント、ascii-art)、またはグラフ(ドット、...)で依存関係を表すことができるプログラムを探しています。

似ている

他の状況でこれを行うプログラムがあります。

  • pactreeまたはdebtreeは、ascii形式などのツリーの各形式またはdotグラフとしてソフトウェアパッケージの依存関係を表示できます。
  • gcc -M source_file.c Cソースファイルの依存関係をmakeルールとして表示します。
  • pstreeは、プロセスツリーのASCII表現を表示します。

進捗

ウェブを検索してもほとんど助けはありませんでした。それは私を試してみるように導いた

make --always-make --silent --dry-run some_target | \
  grep --extended-regexp 'Considering target file|Trying rule prerequisite'

しかし、これを素敵なツリー/グラフとして表現するには、perlまたはpythonでさらに解析コードをハッキングする必要があるようです。そして、この方法で完全で正しいグラフを本当に取得できるかどうかはまだわかりません。

必要条件

いくつかの方法でグラフを制限するのは良いことです(組み込みルールなし、特定のターゲットのみ、深さのみ) -表示可能な形式(「類似」の下のプログラムのように)。

ご質問

  • これを行うことができるプログラムはありますか?
  • 完全で正しい情報を入手できmake -dnq ...ますか?
  • この情報を取得するより良い方法はありますか?
  • この情報を解析するためのスクリプト/試行はすでに存在しますか?

1
ここで理解する重要なことは、依存関係がツリーを形成しないことです。 これらは、DAGとしても知られる有向および(できれば!)非循環グラフを形成します。次の依存関係グラフをスケッチしてみてください。AがBに依存します。AもCに依存しています。BはDに依存します。CはDに依存
ワイルドカード

@Wildcardは知っていますが、私の目的のためには、依存関係をツリーとして表現するだけで十分です。私は、サブグラフを複製して(そして円で切り取って)それをツリーにします。明示的ではないため申し訳ありません。あなたの例では、の出力で問題ありませんprintf 'A\n B\n D\n C\n D\n'。(コメントに改行を入れられないと言ったのは誰ですか?)
ルーカス

「AはBに依存し、BはDに依存し、DはCに依存し、AはDに依存します」とどのように区別できますか?すべてのDAGに完全な順序を課すことができます(DAGは部分的な順序を表すため)が、DAGをツリーに変えることはできません。これは基本的なグラフ理論です。表示できるDAGのツリー表現を作成するためのアルゴリズムを見てみたいと思います。このような基礎となるアルゴリズムがなければ、依存関係をツリーとして表示しようとするツールは、必然的に非常にハッキングされ、エラーが発生しやすくなります。
ワイルドカード

私は再び十分に明示的ではなかったかもしれませんが、Similarの下に挙げた例がそれを明らかにしたと思いました。グラフ理論には興味がありません(少なくともこの質問では)。これに必要なのは、ツリーに似た視覚的表現です(特に、端末に表示する必要がある場合は、dot順序グラフは明らかに問題ありません)。質問を少し更新して、わかりやすくします(願っています)。
ルーカス

2
RANT:正直なところ、makeにはこのようにすぐに使えるものが用意されていないことに少しイライラしています。Makeは世界で最も普及しているビルドシステムの1つであり、この機能は非常に有用であるため、神が何十年もの間そのような機能を追加した誰も存在しなかったことを神が知っていることを理解するのは困難です。この情報を明確に定義されたテキスト形式で出力すれば、まったく十分です。makeはオープンソースであり、この機能は自分でいつでも追加できることを理解しています。そして、もしmakeが私にとって基本的にブラックボックスでなければ、私は信じます!うそつき。
17

回答:


10

同じ作者のmakefile2graphを試してください。同様のツールMakeGraphDependenciesがのjava代わりに記述されていますc

make -Bnd | make2graph | dot -Tsvg -o out.svg

次に、ベクターグラフィックエディターを使用して、必要な接続を強調表示します。


1
私はそのツールを試しました。動作しさえしません(少なくとも私が試したmakeの化身のいずれについても)。ほとんどの場合、メモリアクセス違反が発生します。
17

3

どのターゲットがどの前提条件に依存するかについて、少なくとも明確に構造化された情報を出力する一種のハックを見つけました。欠点は、非常に邪魔になることです。つまり、メイクファイルを変更して、すべてのターゲットのビルドレシピを小さな条件関数にラップする必要があります。簡単な例を投稿します。

getRecipe = $(if $(DEPENDENCY_GRAPH),@echo Target $@ depends on prerequisites "$^",$(1))


VARIABLE_TARGET_NAME = foobar.txt

all : TopLevelTarget

TopLevelTarget : Target_A Target_D
    $(call getRecipe,\
        @echo Building target $@)

Target_A : Target_B
    $(call getRecipe,\
        @echo Building target $@)

Target_D : Target_C
    $(call getRecipe,\
        @echo Building target $@)

Target_B : $(VARIABLE_TARGET_NAME)
    $(call getRecipe,\
        @echo Building target $@)

Target_C :
    $(call getRecipe,\
        @echo Building target $@)

$(VARIABLE_TARGET_NAME) :
    $(call getRecipe,\
        @echo Building target $@)

この例では、手巻きのgetRecipe関数を使用して個々のターゲットのレシピをラップし、そのレシピを実際に実行するか、ビルド中のターゲットと依存する前提条件を単に出力するかを決定します。後者は、変数DEPENDENCY_GRAPHが設定されている場合にのみ発生します(たとえば、環境変数として)。この例では、ビルドレシピはターゲットがビルドされていることを示すエコーにすぎませんが、これを明らかに任意のコマンドに置き換えることができます。

ではDEPENDENCY_GRAPH1に設定し、出力でこの結果:

Target foobar.txt depends on prerequisites ""
Target Target_B depends on prerequisites "foobar.txt"
Target Target_A depends on prerequisites "Target_B"
Target Target_C depends on prerequisites ""
Target Target_D depends on prerequisites "Target_C"
Target TopLevelTarget depends on prerequisites "Target_A Target_D"

これは、解析してドットグラフに変換するのに十分簡単なはずです。

ではDEPENDENCY_GRAPH、すべての設定または0に設定されていないと、出力は次のようになります。

Building target foobar.txt
Building target Target_B
Building target Target_A
Building target Target_C
Building target Target_D
Building target TopLevelTarget

または、言い換えれば、通常のビルドレシピが代わりに使用されます。複雑なレシピでこれが確実に機能するかどうかはまだテストしていません。私が既に遭遇した問題の1つは、複数行のレシピではまったく機能しないことです。

たとえば、最後のターゲットのビルドレシピで、ターゲットがビルドされていると言うことに加えて、実際touchにファイルにしたかった場合:

$(VARIABLE_TARGET_NAME) :
    $(call getRecipe,\
        @echo Building target $@\
        touch $@)

makeそのtouch $@部分は前の行のエコーの一部にすぎないと考えているようです:

Building target foobar.txt touch foobar.txt

私は前の行の末尾にバックスラッシュをオフのままにしておくと、make文句*** unterminated call to functionコール':欠落しているが)'. Stop.、誰もが取得する方法のアイデアがある場合はmake素敵を再生するためには、私はすべての耳です。:)

編集:このアプローチのもう1つの問題は、ビルド結果がまだ存在しない場合にのみ機能することです。make明らかに、最新とみなされるターゲットのビルドレシピを実行しません。


タッチコマンドの;target $@に作品を追加
mug896

2番目の問題では、make -Bすべてのターゲットを無条件に作成するオプションを使用します。
mug896

2

remake --profile(のドロップイン置換make)を使用して、コールグラインド形式の依存関係ツリーを生成しました。

次に、gprof2dotはターゲットツリーのイメージを生成できます。


ドキュメントを間違って理解していますかremake --profile、それが実行するターゲットの依存関係グラフのみを出力しますか?または、何らかの方法ですべてのターゲットのグラフを出力できますか?
ルーカス

実行されるのは1つだけです。しかし、あなたはそれらをすべて–dry-run
Victor Sergienkoで

そうそう、remake --targets -r | grep -v %| grep -v '\t*\.'|xargs remake -n --profile -B有望そうに見えます。
ルーカス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.