2013-01-15 8 views
18

ファイルが存在しない場合にエラー状態を終了する方法はありますか?ファイルがメイクファイルのターゲットに存在するかどうかテストし、存在しない場合は終了する

all: foo 

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

make実行fooを実行allターゲットを実行:私は現在、このような何かをしています。

test -sの条件が満たされない場合、echo/exitステートメントが実行されることが予想されます。

ただし、/usr/bin/gsortが存在する場合でも、echoの結果が表示されますが、exitコマンドは実行されません。これは私が達成しようとしているものとは逆です。

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

+0

私はサブシェルを取得するには、括弧内に '||'の右側を持つ、コマンドラインでこれをしようとすると、期待通りに動作します。私はそれがmakefileで同じかどうかは分かりません。かっこがなければ、テストが肯定的であっても「終了」が実行されます。 – HonkyTonk

答えて

15

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

||&&equal precedenceを持っているので、これは、ある、とあなたがゼロ以外の値で終了しなければならない失敗をしたい場合は、それは、例えば、

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

を書かれていたかのように、シェルはコマンドを解釈exit 1。 そして、あなたは終了をエコーし​​たい場合は、単に;

all: foo 

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

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

all: foo 

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

は、診断メッセージを印刷echoのようなコマンドは、すべてがうまくだと思うしmakeを引き起こし、0の終了ステータスを返しますので、少し物事を複雑にしています。この問題を回避するには、サブシェルゼロ以外の終了ステータス与えることの後にコマンドを実行する必要があります。

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; } 
24

を私はこれは少しであると認識しますこの時点で古いものですが、サブシェルを使ってMakeにファイルが存在するかどうかをテストする必要はありません。

これはまた、実行する方法や実行する方法によって異なります。

そうのように、ワイルドカード機能を使用する:

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

はそれを行うための一つの良い方法です。 ifeq節は、ターゲット自体の前で評価されるため、インデントされません。あなたは、これはすべてのターゲットに対して無条件に発生する場合

、あなただけのターゲットの外に移動することができます:

all: /opt/local/bin/gsort 

/opt/local/bin/gsortが欠落している場合、あなたは以下となります。

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

を簡単に行います/ opt/local/bin/gsort '"というエラーメッセージが表示されます。

しかし、あなたはまた、それにいくつかの素晴らしい説明がしたい場合:ターゲットが.PHONEY宣言されていないと任意の依存関係を持っていない、ルールがファイル場合に呼び出されます場合はGNUで

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

/作りますそのターゲットと一致するものは存在しません。

上記のコードは、/opt/local/bin/gsortが存在しない場合にのみfalseコマンドを起動し、0以外の値を返し、失敗します。

+0

makeが欠落しているすべてのファイルをチェックしてからfalseを返すようにする方法はありますか?そうすれば、誰かがたくさんのファイルを紛失していると、一度に1つではなくすべてが表示されます。 – thepiercingarrow

1

あなたはそのためにwhichまたはtypeシェルコマンドを使用することができ、gsort実行可能ファイルが存在するかどうかをチェックしているので、例えば:

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 
関連する問題