web-dev-qa-db-ja.com

makefileターゲットにファイルが存在するかどうかをテストし、存在しない場合は終了します

ファイルが存在しない場合にエラー状態で終了する方法はありますか?私は現在このようなことをしています:

all: foo

foo:
    test -s /opt/local/bin/gsort || echo "GNU sort does not exist! Exiting..." && exit

makeを実行すると、allターゲットが実行され、fooが実行されます。

期待されるのは、test -s条件に失敗した場合、echo/exitステートメントが実行されます。

ただし、/usr/bin/gsortは存在しますが、echoステートメントの結果を取得しますが、exitコマンドは実行されません。これは私が達成したいと思っていることの反対です。

上記のようなことを行う正しい方法は何ですか?

25
Alex Reynolds

exit 単独では、最後に実行されたコマンドのステータスを返します。この場合、ゼロを返します。つまり、すべてが正常であることを意味します。

これは、||&&等しい優先順位 があり、シェルがコマンドが記述されているかのように解釈するためです。

( test ... || echo ... ) && exit

失敗を通知する場合は、ゼロ以外の値で終了する必要があります。 exit 1。エコーandで終了するには、コマンドを;で区切って順番に並べます

all: foo

foo:
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; }
20
Olaf Dietsche

現時点ではこれは少し古いことを理解していますが、Makeにファイルが存在するかどうかをテストするためにサブシェルを使用する必要さえありません。

また、実行する方法/期待する方法にも依存します。

次のようにワイルドカード関数を使用します。

all: foo
foo:
ifeq (,$(wildcard /opt/local/bin/gsort))
    $(error GNU Sort does not exist!)
endif

それを行う1つの良い方法です。ここで、ifeq句はターゲット自体の前に評価されるため、インデントされないことに注意してください。

これをすべてのターゲットで無条件に実行したい場合は、ターゲットの外に移動するだけです。

ifeq (,$(wildcard /opt/local/bin/gsort))
$(error GNU Sort does not exist!)
endif
27
KingRadical

Makeのすべてのコマンドラインは、独自のサブシェルで実行されます。したがって、exitを実行すると、そのサブシェルだけが終了します。メイクファイル全体ではありません。デフォルトでは、サブシェルが失敗した終了ステータスを返すと、makeの実行が停止します(慣例により、0は成功を意味するため、他のものは実行を停止します)。最も簡単な方法は、testコマンドの終了ステータスを使用することです。

all: foo

foo:
    test -s /opt/local/bin/gsort

診断メッセージを印刷すると、echoなどのコマンドが終了ステータス0を返し、makeがすべて正常であると判断するため、事態は少し複雑になります。これを回避するには、サブシェルにゼロ以外の終了ステータスを与えるコマンドを実行する必要があります。

all: foo

foo:
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; exit 1; }

または単に

all: foo

foo:
    test -s /opt/local/bin/gsort || { echo "GNU sort does not exist! Exiting..."; false; }
7
laindir

単純に:

all: /opt/local/bin/gsort

で、もし /opt/local/bin/gsortが欠落している場合、「ターゲット `/ opt/local/bin/gsort 'を作成するルールがありません」というエラーメッセージが表示されます。

しかし、それを使って素敵な説明もしたい場合は:

/opt/local/bin/gsort:
    echo "GNU sort does not exist! Exiting..."
    false

GNU/Makeでは、ターゲットが宣言されていない場合は.PHONEYに依存関係がなく、そのターゲットに一致するファイルが存在しない場合にルールが呼び出されます。

上記のコードは、falseコマンドを/opt/local/bin/gsortは存在せず、0以外の値を返し、makeは失敗します。

2
Chen Levy

gsort実行可能ファイルが存在するかどうかを確認しているので、そのためにwhichまたはtype Shellコマンドを使用できます。

all: foo
  :

foo:
  which gsort || exit 1
  # or
  type gsort || exit 1

エラーメッセージは自動的に印刷されるため、必要ありません。

/ bin/sh:行0:タイプ:gsort:見つかりません

明らかです。


または、testまたは[ (見る: help test/help [構文の場合)、例:.

test -x /opt/local/bin/gsort || { echo Error msg; exit 1; }

指定されたファイルが存在し実行可能かどうかを確認し、存在しない場合はメッセージを表示して終了します。括弧は、コマンドをグループ化することにより(左から右へ)演算子の通常の優先順位をオーバーライドするために重要です(Compound Commandsセクションman bash詳細については)。


別の方法は、ルールのターゲットを使用してファイルが存在するかどうかを確認し、allに依存関係として追加することです。

all: /opt/local/bin/gsort
  @echo Success.

/opt/local/bin/gsort:
  @echo "GNU sort does not exist! Exiting..."
  exit 1

結果:

$ make
GNU sort does not exist! Exiting...
exit 1
make: *** [/opt/local/bin/gsort] Error 1
2
kenorb