web-dev-qa-db-ja.com

makefileでターゲットのリストを取得するにはどうすればよいですか?

少し熊手(Ruby makeプログラム)を使用しましたが、利用可能なすべてのターゲットのリストを取得するオプションがあります。

> rake --tasks
rake db:charset      # retrieve the charset for your data...
rake db:collation    # retrieve the collation for your da...
rake db:create       # Creates the databases defined in y...
rake db:drop         # Drops the database for your curren...
...

しかし、GNU makeでこれを行うオプションはないようです。

どうやら、2007年の時点で、コードはほとんどそこにあります- http://www.mail-archive.com/[email protected]/msg06434.html

とにかく、メイクファイルからターゲットを抽出するための小さなハックを作成しました。メイクファイルに含めることができます。

list:
    @grep '^[^#[:space:]].*:' Makefile

定義されたターゲットのリストが表示されます。これはほんの始まりにすぎません-たとえば、依存関係を除外しません。

> make list
list:
copy:
run:
plot:
turnin:
169
Brian Burns

これは、次のように @ nobarの優れたアプローチ を改善する試みです。

  • より堅牢なコマンドを使用してターゲット名を抽出します。これにより、誤検出を防ぐことができます(また、不要なsh -cがなくなります)
  • currentディレクトリのmakefileを常にターゲットにしません。 -f <file>で明示的に指定されたメイクファイルを尊重します
  • 隠されたターゲットを除外-慣例により、これらは名前が文字でも数字でも始まらないターゲットです
  • single偽のターゲットで間に合う
  • コマンドの前に@を付けて、実行前にコマンドがエコーされないようにします

奇妙なことに、GNU makeには、メイクファイルで定義されているターゲットの名前だけをリストする機能がありません。 -pオプションは、すべてのターゲットを含む出力を生成しますが、他の多くの情報にそれらを埋め込みます。

以下のルールをGNU makeのmakefileに配置して、すべてのターゲット名をアルファベット順にリストする_listという名前のターゲットを実装します。 :make listとして呼び出します:

.PHONY: list
list:
    @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'

重要:これを貼り付ける際には、最後の行が正確に1つの実際のタブでインデントされていることを確認してくださいchar。(スペースはnot work)

並べ替えは、ターゲットの結果リストが最良のオプションであることに注意してください。これは、not並べ替えは、メイクファイルにターゲットが表示される順序で有用な順序を生成しないためです。 not保存されます。
また、複数のターゲットを含むルールのサブターゲットは常に出力されますseparately。したがって、ソートのため、通常はnotが隣り合って表示されます。 ;たとえば、a z:で始まるルールはnotターゲットaおよびzがリストされます隣同士追加のターゲットがあります。

ルールの説明

  • .PHONY: list
    • ターゲットリストに偽のターゲット、つまり1つのnotを参照しているfileを参照しているため、レシピを呼び出す必要があります無条件
  • $(MAKE) -prRn -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null

    • Makefileから派生したデータベースを印刷および解析するために、makeを再度呼び出します:
      • -pはデータベースを出力します
      • -Rrは、組み込みのルールと変数の包含を抑制します
      • -qは、ターゲットの最新の状態のみをテストします(何もリメイクせずに)が、それ自体では、すべての場合でレシピコマンドの実行を妨げません。したがって:
      • -f $(lastword $(MAKEFILE_LIST))は、-f ...で暗黙的または明示的に対象指定されたかどうかに関係なく、元の呼び出しと同じmakefileが対象となるようにします。
        Caveatメイクファイルにincludeディレクティブ。これに対処するには、変数THIS_FILE := $(lastword $(MAKEFILE_LIST))before any includeディレクティブを定義し、代わりに-f $(THIS_FILE)を使用します。
      • :意図的に無効なターゲットです。これはコマンドが実行されないことを保証する; 2>/dev/nullは、結果のエラーメッセージを抑制します。注:これは、GNU make 3.82の場合でも、-pデータベースの印刷に依存しています。悲しいことに、GNU makeはjustデータベースを印刷するための直接的なオプションを提供せず、alsoデフォルト(または指定された)タスクを実行しません。特定のMakefileをターゲットにする必要がない場合は、manページで推奨されているように、make -p -f/dev/nullを使用できます。
  • -v RS=

    • これは、入力を連続した空でない行のブロックに分割するawkイディオムです。
  • /^# File/,/^# Finished Make data base/
    • すべてのターゲットを含む出力の行の範囲に一致します(GNU make 3.82の時点でtrue)-解析をこの範囲に制限することにより、他の出力セクションからの誤検出に対処する必要がありません。
  • if ($$1 !~ "^[#.]")
    • ブロックを選択的に無視します:
      • # ...ブロックが# Not a target:で始まる非ターゲットを無視します
      • . ...特別なターゲットを無視
    • 他のすべてのブロックは、明示的に定義されたターゲットの名前のみを含む行で始まり、その後に:が続く必要があります
  • egrep -v -e '^[^[:alnum:]]' -e '^$@$$'は、出力から不要なターゲットを削除します:
    • '^[^[:alnum:]]' ... hiddenターゲットを除外します。これは、慣例により、文字でも数字でも始まらないターゲットです。
    • '^$@$$' ... listターゲット自体を除外します

make listを実行すると、すべてのターゲットがそれぞれの行に出力されます。代わりにxargsにパイプして、スペースで区切られたリストを作成できます。

100
mklement0

(少なくとも)Bashでは、これはタブ補完で自動的に実行できます。

make(space)(tab)(tab)
163
nobar

私はこれらの2つの答えを組み合わせました: https://stackoverflow.com/a/9524878/86967 および https://stackoverflow.com/a/7390874/86967 これをメイクファイル内から使用できるようにエスケープします。

.PHONY: no_targets__ list
no_targets__:
list:
    sh -c "$(MAKE) -p no_targets__ | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' | grep -v '__\$$' | sort"

$ make -s list
build
clean
default
distclean
doc
fresh
install
list
makefile ## this is kind of extraneous, but whatever...
run
25
nobar

多くの場合、これは明らかに動作しませんが、MakefileがCMakeによって作成された場合、make helpを実行できる可能性があります。

$ make help
The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... install
etc
20
Timmmm

makeのbash補完がインストールされている場合、補完スクリプトは関数_make_target_extract_scriptを定義します。この関数は、ターゲットをリストとして取得するために使用できるsedスクリプトを作成することを目的としています。

次のように使用します。

# Make sure bash completion is enabled
source /etc/bash_completion 

# List targets from Makefile
sed -nrf <(_make_target_extract_script --) Makefile
13
hek2mgl

mklement0が指摘している のように、すべてのMakefileターゲットをリストする機能がGNU-makeに欠けており、彼の答えと他の人がこれを行う方法を提供しています。

ただし、元の投稿には rake も記載されており、そのtasksスイッチは、rakefile内のすべてのタスクをリストするのとは少し異なることを行います。 Rakeは、説明が関連付けられているタスクのリストのみを提供します。説明のないタスク リストに表示されません 。これにより、作成者はカスタマイズされたヘルプの説明を提供したり、特定のターゲットのヘルプを省略したりすることができます。

各ターゲットの説明 を指定してrakeの動作をエミュレートしたい場合、これを行う簡単な方法があります。リストしたい各ターゲットのコメントに説明を埋め込みます。

説明をターゲットの隣に配置するか、私がよく行うように、次のようにターゲットの上のPHONY仕様の隣に説明を配置できます。

.PHONY: target1 # Target 1 help text
target1: deps
    [... target 1 build commands]

.PHONY: target2 # Target 2 help text
target2:
    [... target 2 build commands]

...                                                                                                         

.PHONY: help # Generate list of targets with descriptions                                                                
help:                                                                                                                    
    @grep '^.PHONY: .* #' Makefile | sed 's/\.PHONY: \(.*\) # \(.*\)/\1 \2/' | expand -t20

どちらが得られますか

$ make help
target1             Target 1 help text
target2             Target 2 help text

...
help                Generate list of targets with descriptions

this Gist および here にも短いコード例があります。

繰り返しますが、これはMakefile内のすべてのターゲットをリストする問題を解決しません。たとえば、生成された可能性のある大きなMakefileまたは他の誰かが作成したMakefileがあり、ターゲットを掘り下げずにターゲットを一覧表示する簡単な方法が必要な場合、これは役に立ちません。

ただし、Makefileを作成していて、一貫性のある自己文書化方法でヘルプテキストを生成する方法が必要な場合は、この手法が役立つ場合があります。

10
jsp

@ nobar's answer 便利な方法を示していますタブ補完を使用してmakefileのターゲットを一覧表示する

  • これは、この機能を提供するプラットフォームに最適ですデフォルト(例:Debian、Fedora)。

  • 他のプラットフォーム(例:bunt)では、 @ hek2mglの回答 で示されるように、この機能をexplicitly loadする必要があります。

    • . /etc/bash_completionは、makeの機能を含むいくつかのタブ補完機能をインストールします
    • または、make:のタブ補完onlyをインストールする場合
      • . /usr/share/bash-completion/completions/make
  • この機能をまったく提供しないプラットフォームの場合、OSXのように、次のコマンドのソース(から適応)- ここ )実装するには:
_complete_make() { COMPREPLY=($(compgen -W "$(make -pRrq : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($1 !~ "^[#.]") {print $1}}' | egrep -v '^[^[:alnum:]]' | sort | xargs)" -- "${COMP_WORDS[$COMP_CWORD]}")); }
complete -F _complete_make make
  • 注:これは、Linuxディストリビューションに付属するタブ補完機能ほど高度ではありません。最も顕著なのは、currentディレクトリのmakefileを常に対象とする 、コマンドラインが-f <file>で異なるメイクファイルをターゲットにしている場合でも。
4
mklement0

これは、 jsp の非常に役立つ回答( https://stackoverflow.com/a/45843594/814145 )の修正です。ターゲットのリストだけでなく、それらの説明も取得するというアイデアが好きです。 jsp のMakefileは、コメントをコメントとして配置します。これは、ターゲットのdescription echoコマンドで頻繁に繰り返されることがわかりました。そのため、代わりに、各ターゲットのechoコマンドから説明を抽出します。

Makefileの例:

.PHONY: all
all: build
        : "same as 'make build'"

.PHONY: build
build:
        @echo "Build the project"

.PHONY: clean
clean:
        @echo "Clean the project"

.PHONY: help
help:
        @echo -n "Common make targets"
        @echo ":"
        @cat Makefile | sed -n '/^\.PHONY: / h; /\(^\t@*echo\|^\t:\)/ {H; x; /PHONY/ s/.PHONY: \(.*\)\n.*"\(.*\)"/    make \1\t\2/p; d; x}'| sort -k2,2 |expand -t 20

make helpの出力:

$ make help
Common make targets:
    make all        same as 'make build'
    make build      Build the project
    make clean      Clean the project
    make help       Common make targets

ノート:

  • jsp の回答と同じ、PHONYターゲットのみがリストされる場合があります。
  • さらに、レシピの最初のコマンドとしてechoまたは:コマンドを持つPHONYターゲットのみがリストされます。 :は「何もしない」という意味です。上記のallターゲットなど、エコーが不要なターゲットに使用します。
  • helpターゲットがmake help出力に「:」を追加するための追加のトリックがあります。
1
Penghe Geng

これは、makeターゲットに必要なビルドターゲット(およびその依存関係)を確認したいので、私にとっては役に立ちました。 makeターゲットは「。」で始めることができないことを知っています。キャラクター。サポートされている言語がわからないので、egrepのブラケット式を使用しました。

cat Makefile | egrep "^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$"
1
seanlum

ここで実行可能なソリューションはたくさんありますが、私が言っているように、「一度やる価値があれば、もう一度やる価値があります。」私は(tab)(tab)を使用するためにサジェスチョンを支持しましたが、一部の人が指摘したように、完了サポートがない場合があります。または、多くのインクルードファイルがある場合は、ターゲットが定義されている場所を簡単に知ることができます。

私はサブメイクで以下をテストしていません...それはうまくいかないと思います。私たちが知っているように、再帰は有害とみなされます。

.PHONY: list ls
ls list :
    @# search all include files for targets.
    @# ... excluding special targets, and output dynamic rule definitions unresolved.
    @for inc in $(MAKEFILE_LIST); do \
    echo ' =' $$inc '= '; \
    grep -Eo '^[^\.#[:blank:]]+.*:.*' $$inc | grep -v ':=' | \
    cut -f 1 | sort | sed 's/.*/  &/' | sed -n 's/:.*$$//p' | \
    tr $$ \\\ | tr $(open_paren) % | tr $(close_paren) % \
; done

# to get around escaping limitations:
open_paren := \(
close_paren := \)

私が好きな理由:

  • インクルードファイルごとにターゲットを一覧表示します。
  • 生の動的ターゲット定義を出力します(変数区切り文字をモジュロに置き換えます)
  • 各行を新しい行に出力します
  • より明確に見える(主観的意見)

説明:

  • mAKEFILE_LISTのforeachファイル
  • ファイルの名前を出力する
  • インデントされず、コメントではなく、ピリオドで始まらないコロンを含むgrep行
  • 即時代入式を除外します(:=)
  • ルール依存関係の切り取り、ソート、インデント、およびチョップ(コロンの後)
  • 展開を防ぐための可変の区切り文字

サンプル出力:

 = Makefile = 
  includes
  ls list
 = util/kiss/snapshots.mk = 
  rotate-db-snapshots
  rotate-file-snapshots
  snap-db
  snap-files
  snapshot
 = util/kiss/main.mk = 
  dirs
  install
   %MK_DIR_PREFIX%env-config.php
   %MK_DIR_PREFIX%../srdb
1
ginkgoMZD

これはきれいではありませんが、私にとっては仕事をしました。

make -p 2&>/dev/null | grep -A 100000 "# Files" | grep -v "^$" | grep -v "^\(\s\|#\|\.\)" | grep -v "Makefile:" | cut -d ":" -f 1

内部データベースをダンプするmake -pを使用し、stderrを捨て、素早く汚いgrep -A 100000を使用して出力の下部を保持します。次に、いくつかのgrep -vで出力をクリーンアップし、最後にcutを使用して、コロンの前にあるもの、つまりターゲットを取得します。

これで、ほとんどのMakefileのヘルパースクリプトに十分です。

編集:内部ルールであるgrep -v Makefileを追加しました

1
Lisael

上記に対するさらに別の回答。

ターミナルでcatとawkのみを使用してMacOSXでテスト済み

cat Makefile | awk '!/Shell/ && /^[A-z]/ {print $1}' | awk '{print substr($0, 1, length($0)-1)}'

以下のようなmakeファイルを出力します。

target1

target2

target3

makefileでは、同じステートメントである必要があります。$ variableではなく$$ variableを使用して変数をエスケープしてください。

説明

cat-コンテンツを吐き出します

-次のawkへのパイプ解析出力

awk-「Shell」を除く正規表​​現を実行し、「A-z」行のみを受け入れて、最初の$ 1列を出力します

awk-リストから最後の文字「:」を再度削除します

これは大まかな出力であり、AWKだけでよりファンキーなことができます。 sedは、BSDのバリアントでは一貫性がないため、* nixでは機能するがMacOSXなどのBSDでは失敗するなど、sedを避けるようにしてください。

その他

これを(変更を加えて)makeのファイル、デフォルトのbash-completionフォルダー/ usrに追加できるはずです。 /local/etc/bash-completion.d/は、「tab tab ".. 1つのライナースクリプトに基づくターゲット。

0
Jimmy M.G. Lim