変数から名前を計算することにより、多数のターゲットをその場で作成するかなり大きなメイクファイルがあります。 (例:foo $(VAR):$(PREREQS))。これらの変数を展開した後、gnu makeがターゲットのリストを吐き出すと確信できる方法はありますか?
任意のメイクファイルのターゲットを取得できるようにしたいと思います。シェルの補完関数を作成しようとしています。
make -pn
(つまりmake --print-data-base --dry-run
)からの出力を解析できますか?すべての変数、ルール、暗黙ルール、およびどのコマンドが面倒な詳細で実行されるかを出力します。
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'
Make argの補完から取得します。これは魅力のように機能します。
これがgnu makeだけのものかどうかはわかりませんが、これはうまく機能します。
make help
いくつかのレスポンダーは、make -pn
を使用することを提案しました。これは、ルールのデータベースを印刷しますが、多かれ少なかれ何も実行しません。このアプローチの問題は、-n
がすべての再帰makeを呼び出すことであり、通常のビルドで呼び出されるすべてのコマンドを出力するため、必要以上に多くの作業を行うことです。より効率的な解決策は、次の内容で簡単なmakefile、dummy.mkを作成することです。
__all_targets__: ; #no-op
Makeを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秒です。
GitHubでbash makeの完了 を確認してください。
編集:参考までに、別の回答の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完了スクリプトよりもはるかに完全なスクリプトです。
これは私がリンクした元のスクリプトではありませんが、はるかに単純で、タッチが速いです。
これは、Todd Hodesソリューションに基づくエイリアスのコードです
alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'
これにより、素敵な出力が得られます。
make -pn | Perl -F: -ane 'print "$F[0]\n" if /^\w+\s*:/' | sort
いくつかのsedおよびegrepマジックを使用した非常に素晴らしいソリューションがあります: https://Gist.github.com/pvdb/777954
私はこのパーティーに少し遅れていると思いますが、特定のコマンドを探しているなら、試すことができます
make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'
これは主に機能しますが、vpath
ディレクティブのようなターゲットではないものがまだ含まれている場合があります。 make
の組み込みルールに依存しない場合は、make -qpR
パイプラインの最初のコマンドとして。
Rubyソリューション:
`make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}
私はsolaris 10とturbo C Shellに取り組んでいます。与えられたソリューションは、私のmakefileプロジェクトでは機能しません。上記のコマンドラインを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
。
私は同じ質問を探しに行き、このスピンを思いつきました:
make -pn | sed -rn '/^[^# \t\.%].*:/p'
これにより、すべてのコメント行、パターンルール(タブで始まる行)、すべての組み込み関数(例.c.o
および%.o: %.c
パターン)。