私は、変数から名前を計算することによって多数のターゲットをその場で作成するかなり大きなメイクファイルを持っています。(例:foo $(VAR):$(PREREQS))。これらの変数を展開した後、gnu makeがターゲットのリストを吐き出すことを確信できる方法はありますか?
任意のメイクファイルのターゲットを取得できるようにしたいのですが。シェルの補完関数を記述しようとしています。
私は、変数から名前を計算することによって多数のターゲットをその場で作成するかなり大きなメイクファイルを持っています。(例:foo $(VAR):$(PREREQS))。これらの変数を展開した後、gnu makeがターゲットのリストを吐き出すことを確信できる方法はありますか?
任意のメイクファイルのターゲットを取得できるようにしたいのですが。シェルの補完関数を記述しようとしています。
回答:
make -pn
(つまりmake --print-data-base --dry-run
)からの出力を解析できますか?すべての変数、ルール、暗黙のルール、および面倒な詳細で実行されるコマンドを出力します。
make -pn | sed -rn '/^[^# \t\.%].*:[^=]?/p'
make -pnr
。-r
暗黙のルールを削除します。
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
魅力のように機能するmake arg完了から取得。
~/bin
エイリアスを使用するのではなく、それをシェルスクリプトに挿入するだけです。よく働く; ありがとう!
alias mkl="make -qp | awk -F':' '/^[a-zA-Z0-9][^\$#\/\t=]*:([^=]|\$)/ {split(\$1,A,/ /);for(i in A)print A[i]}' | sort"
引用ゲームの2分間を節約するエイリアス:-)
| sort -u
より便利に見えます:)
これが単なるGNU makeかどうかはわかりませんが、これはうまく機能します。
make help
いくつかのレスポンダーは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秒。
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
。
make
、似ているが友好的なものを提案しているようです。つまり、make -p -f/dev/null
-f /dev/null
とmake
、通常のメイクファイルが解析されなくなるため、組み込みのルールのみが出力されます。それが私の解決策がを指定して-f Makefile -f dummy.mk
いる理由です。しかし、それでも十分ではありません。なぜなら-n
、を使用make
すると、makefile内のルールの実行も実際に開始されるからです。残念ながら、最初に提示したように、ソリューションを簡略化できる変更については知りません。
-n
...」と表示されます
編集:参考までに、別の回答の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補完スクリプト)が十分に機能しないためです。
これは私がリンクした元のスクリプトではありませんが、はるかに単純で、タッチが高速です。
sedとegrepの魔法を使った非常に素晴らしい解決策があります:https : //gist.github.com/pvdb/777954
私はこのパーティーに少し遅れていると思いますが、特定のコマンドを探しているなら、あなたは試すことができます
make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'
これはほとんど機能しますが、vpath
ディレクティブのようなターゲット以外のものも含まれている可能性があります。make
の組み込みルールに依存しない場合make -qpR
は、パイプラインの最初のコマンドとして使用できます。
私はソラリス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
その他の重要でないバージョンデータ
このソリューションを別のスレッドで見つけました:
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
ます。
確かに、いつ吐き出したいですか?
ルールの実行時にターゲットの名前を報告するには、ルールに行を追加します。
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エミュレータに近いものを書く必要があります。非現実的。
単純なルールのターゲットを確認するには、任意のメイクファイルで動作するメイクファイルスキャナーとして機能するメイクファイルを記述します。
これは印象的な作品です。目標は努力の価値があると確信していますか?
grep ^[a-z].*\:$ Makefile | sed s,:,,g
:=
)でも誤検出が発生します。