定義に変数を含むGNU makeの目標/ターゲットをリストします


100

私は、変数から名前を計算することによって多数のターゲットをその場で作成するかなり大きなメイクファイルを持っています。(例:foo $(VAR):$(PREREQS))。これらの変数を展開した後、gnu makeがターゲットのリストを吐き出すことを確信できる方法はありますか?

任意のメイクファイルのターゲットを取得できるようにしたいのですが。シェルの補完関数を記述しようとしています。

回答:


79

make -pn(つまりmake --print-data-base --dry-run)からの出力を解析できますか?すべての変数、ルール、暗黙のルール、および面倒な詳細で実行されるコマンドを出力します。


この答えは他の答えよりもはるかに良く見えます。
マットジョイナー、

私はこれがはるかに良いことに同意します。思ったよりもまだまだ機能しますが、他に妥当なものはなさそうで、GNU makeには必要なものに対する便利なフラグがないので、それを答えとしてマークします。
BitShifter

6
Makefileがターゲットを動的に生成する場合、出力は指定したターゲットに依存する可能性があることに注意してください。出力は、環境変数またはmakeコマンドで指定されたmake変数の値にも依存する場合があります。
reinierpost 2011年

6
私は簡潔さが好きです。+1自分のスピンを追加(以下の回答で説明):make -pn | sed -rn '/^[^# \t\.%].*:[^=]?/p'
Jamie

提案するmake -pnr-r暗黙のルールを削除します。
sjbx

114
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     

魅力のように機能するmake arg完了から取得。


2
二重引用符で囲んでエイリアスを作成しようとしましたが、最初のコンマでawkに構文エラーが発生しました...シェル(bash)エイリアスでこれを正しくエスケープする方法についての考えはありますか?
drfrogsplat 2012年

3
それが定義されている場所と関係があると思います。それがエイリアスとして定義されている場合、その作業ディレクトリは、それが定義されているディレクトリになると思います。明らかに、awkの部分は、隠しディレクトリのドットが好きではないようです。関数の定義は機能します。
Ibrahim

~/binエイリアスを使用するのではなく、それをシェルスクリプトに挿入するだけです。よく働く; ありがとう!
mpontillo 2015

3
alias mkl="make -qp | awk -F':' '/^[a-zA-Z0-9][^\$#\/\t=]*:([^=]|\$)/ {split(\$1,A,/ /);for(i in A)print A[i]}' | sort"引用ゲームの2分間を節約するエイリアス:-)
Ciro Santilli郝海东冠状病六四事件法轮功

1
| sort -uより便利に見えます:)
sherpya

14

これが単なるGNU makeかどうかはわかりませんが、これはうまく機能します。

make help


これは非常に便利で、他のメソッドのいずれかのカスタムエイリアスよりも覚えやすくなっています。
イブラヒム

8
GNU Make 3.81で実際に機能していない、おそらくmakefileのターゲット:「make:***ターゲットを「ヘルプ」にするルールはありません。停止」
a1an

8
これはMakefileの "help"ターゲットを呼び出すだけです。存在する場合は(ターゲットの完全なリストではなく)何かを出力し、存在しない場合(一般的な状況)は救済します。
pfalcon 2013

2
cmakeは読みやすい「ヘルプ」ターゲットを生成するようです。
ステファン・

これはすごい!:) cmakeに行く
Jeef

10

いくつかのレスポンダーはmake -pn、ルールのデータベースを出力しますが、何も実行しない-多かれ少なかれ-の使用を提案しています。このアプローチの問題は、-nすべての再帰的なmakeを呼び出し、通常のビルドで呼び出したすべてのコマンドを出力するため、必要以上に多くの作業を実行することです。より効率的な解決策は、次の内容で簡単なmakefile、dummy.mkを作成することです。

__all_targets__: ; #no-op

ここでmake asを呼び出しますmake -p -f Makefile -f dummy.mk __all_targets__。実質的なビルドでは、makeによって生成される出力量の違いは重要です。例えば:

$ gmake -pn | wc
 138985 2632330 69612711
$ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
  21673   93437  878985

実行時間も劇的に改善されました-最初のバージョンでは2.063秒、2番目のバージョンでは0.059秒。


1
きちんとしたアイデア、巨大なビルドシステムで作業するすべての人がそれを高く評価します。Androidジンジャーブレッドツリーの統計(再帰的なmakeを使用しないため、節約はそれほど大きくはありませんが、良いです): " time make -pn | wc -l":1338738 real 0m47.754s." time make -f Makefile -f dummy.mk -pn __all_targets__ | wc -l":938621 real 0m40.219s
pfalcon 2013

いい視点ね。のmanページはmake、似ているが友好的なものを提案しているようです。つまり、make -p -f/dev/null
Davide

@Davideはうまく機能しません。指定する-f /dev/nullmake、通常のメイクファイルが解析されなくなるため、組み込みのルールのみが出力されます。それが私の解決策がを指定して-f Makefile -f dummy.mkいる理由です。しかし、それでも十分ではありません。なぜなら-n、を使用makeすると、makefile内のルールの実行も実際に開始されるからです。残念ながら、最初に提示したように、ソリューションを簡略化できる変更については知りません。
Eric Melski 2016

もちろんそうです。それは述べしかし、メイクのmanページには、バグがあります:「すべてのファイル、使用のメイクをリメイクしようとせずにデータ・ベースを印刷するには-p -fを/ dev / null」
ダヴィデ

私の以前のコメントに対するわずかな修正:「...がない ため-n...」と表示されます
Eric Melski


7

編集:参考までに、別の回答のdebian bash完了gitリポジトリに、bash完了のユースケースに合わせて調整されたこのスクリプトの拡張バージョンが組み込まれました。

#!/bin/bash

SCRIPT='
  /^# Make data base/,/^# Files/d             # skip until files section
  /^# Not a target/,+1          d             # following target isnt
  /^\.PHONY:/                   d             # special target
  /^\.SUFFIXES:/                d             # special target
  /^\.DEFAULT:/                 d             # special target
  /^\.PRECIOUS:/                d             # special target
  /^\.INTERMEDIATE:/            d             # special target
  /^\.SECONDARY:/               d             # special target
  /^\.SECONDEXPANSION/          d             # special target
  /^\.DELETE_ON_ERROR:/         d             # special target
  /^\.IGNORE:/                  d             # special target
  /^\.LOW_RESOLUTION_TIME:/     d             # special target
  /^\.SILENT:/                  d             # special target
  /^\.EXPORT_ALL_VARIABLES:/    d             # special target
  /^\.NOTPARALLEL:/             d             # special target
  /^\.ONESHELL:/                d             # special target
  /^\.POSIX:/                   d             # special target
  /^\.NOEXPORT:/                d             # special target
  /^\.MAKE:/                    d             # special target

# The stuff above here describes lines that are not
#  explicit targets or not targets other than special ones
# The stuff below here decides whether an explicit target
#  should be output.

  /^[^#\t:=%]+:([^=]|$)/ {                    # found target block
    h                                         # hold target
    d                                         # delete line
  }
  /^# File is an intermediate prerequisite/ { # nope
    s/^.*$//;x                                # unhold target
    d                                         # delete line
  }
  /^([^#]|$)/ {                               # end of target block
    s/^.*$//;x                                # unhold target
    s/:.*$//p                                 # write current target
    d                                         # hide any bugs
  }
'

make -npq .DEFAULT 2>/dev/null | sed -n -r "$SCRIPT" \
  | sort | uniq

これはdebian bash補完スクリプトよりもはるかに完全なスクリプトです。質問が求めるものである生成されたルールの結果を提供し、トップ投票の回答(debian gitサーバーでのdebian bash補完スクリプト)が十分に機能しないためです。

これは私がリンクした元のスクリプトではありませんが、はるかに単純で、タッチが高速です。


ところで、改造、テキストのニュアンスのためにこの回答がすべてのポリシーに完全に一致していない場合は、削除する前にコメントしてください。この質問が実際に完全で有効な回答を得ることができるように、必要に応じて合法的な調整を行います。
codeshot、

簡単なテストとして、gccソースコードを取得し、。/ configure && time〜/ makecomp.sh |を実行しました。wc -lここで〜/ makecomp.shが私の答えです。...出力の構成... config.status:Makefile 3312 real 0m0.401s user 0m0.412s sys 0m0.028s
codeshot

別のテストとして、私はcodeshot.blogspot.co.uk/2012/08/…でデモのメイクファイルを使用しました。これは、単体テストのパスを作成およびチェックするための疑似ルールを生成します。この例では、典型的なクロスプラットフォームのautoconfプロジェクトよりもmakeの機能を多く使用しているため、この回答のスクリプトは14個の実際のターゲットを返しますが、ubuntuでのmakeのbash完了は、2つの有用なルールと5つのソースファイルのみを返します。
codeshot

4

これは、Todd Hodesソリューションに基づくエイリアスのコードです

alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'

3

これは素晴らしい出力を提供します:

make -pn | perl -F: -ane 'print "$F[0]\n" if /^\w+\s*:/' | sort


2

私はこのパーティーに少し遅れていると思いますが、特定のコマンドを探しているなら、あなたは試すことができます

make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'

これはほとんど機能しますが、vpathディレクティブのようなターゲット以外のものも含まれている可能性があります。makeの組み込みルールに依存しない場合make -qpRは、パイプラインの最初のコマンドとして使用できます。


freetz(.org)で試してみました。含まれている多くのメイクファイルをリストし、すべてのターゲットをリストしていません。
Robert Siemer

1

Rubyソリューション:

`make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}

1

私はソラリス10とターボCシェルに取り組んでいます。与えられたソリューションは、私のメイクファイルプロジェクトでは機能しません。上記のコマンドラインをtcsh構文に変更した後でも。しかし、私はあなたが使用して簡単な解決策を得ることができることを発見しました

remake --tasks | grep -v "clean some static output or just grep tabs on start of line" | awk ´{print $1}´

リメイク版:

remake --version

です

GNU Make 3.82+dbg0.8
Built for sparc-sun-sparc2-9

その他の重要でないバージョンデータ


0

私は同じ質問を探しに行き、このスピンを思いつきました:

make -pn | sed -rn '/^[^# \t\.%].*:/p'

これにより、すべてのコメント行、パターンルール(タブで始まる行)、すべての組み込み関数(例.c.o%.o: %.cパターン)が削除されます。


受け入れられた回答からのコメントを読みませんでした: ジャックの回答の+1 ... gist.github.com/777954 – pvandenberk Jan 13 at 14:47
Jamie

0

このソリューションを別のスレッドで見つけました:

sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\""

また、次のものに追加することもできますMakefile

list:
    sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\\""

そして、実行しmake listます。


-1

確かに、いつ吐き出したいですか?

ルールの実行時にターゲットの名前を報告するには、ルールに行を追加します。

foo$(VAR): $(PREREQS)
    @echo now making the foo target: $@
    do_other_stuff...

それらすべてを一度に吐き出すには、別のPHONYターゲットを作成します。

.PHONY: show_vars
show_vars:
    @echo foo$(VAR)
    @echo bar$(PARAM) blah$(FLAG)
    # and so on

そして、これはあなたのデフォルトターゲットの前提条件にすることができます:

all: show_vars
    ...

編集:
任意のメイクファイルのすべての可能なターゲットを表示する方法が必要です。上手...

それを正確に行い、たとえばevalステートメントによって構築されたルールを含む、洗練されたメイクファイルに対処できるようにするには、Makeエミュレータに近いものを書く必要があります。非現実的。

単純なルールのターゲットを確認するには、任意のメイクファイルで動作するメイクファイルスキャナーとして機能するメイクファイルを記述します。

  1. sedを使用して、メイクファイルからすべてのターゲット名を取得します。
  2. 変数を展開するために使用するmakefileを「含める」。
  3. `show_%:; すべてのターゲットを印刷するには、$$ * `をエコーし​​ます

これは印象的な作品です。目標は努力の価値があると確信していますか?


私が望むものではない。私が持っている可能性のある任意のメイクファイルのターゲットのリストを吐き出せるようにしたいのですが。私は自分のシェル用の引数補完関数を書こうとしているのですが、makefileが賢明な助けを持っていることに依存できません。
BitShifter

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.