2012-06-18 20 views
5

特定の前提条件が満たされない場合、$(error ...)を使用してメイクプロセスを中止します。 fails_to_workターゲットは、失敗すると打ち切ります。test -d /foobar

BAD.mk

all: this_works fails_to_work 

this_works: 
     @echo echo works... 
     @test -d ~ || echo ~ is not a directory 
     @test -d /foobar || echo /foobar is not a directory 

fails_to_work: 
     @echo error does not work... 
     @test -d ~ || $(error ~ is not a directory) 
     @test -d /foobar || $(error /foobar is not a directory) 

$は、あなたが見ることができるように、いなくても "エラーが動作しません..." BAD.mk

echo works... 
/foobar is not a directory 
BAD.mk:9: *** ~ is not a directory. Stop. 

-f作る画面に表示されます。 fails_to_workのレシピが開始される前に失敗します。これをどうすれば解決できますか?私のユースケースの1つは@test -d $(MY_ENV_VAR)ですが、この例ではハードコーディングされたパスとは異なるとは思われません。

UPDATE $あなたは条件付きで動作しない、メイクファイルのものを呼び出すために、レシピにシェルのものを取得しようとしている--version

GNU Make 3.81 
Copyright (C) 2006 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. 
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE. 

This program built for x86_64-pc-linux-gnu 

答えて

5

を作る

(バージョン情報)あなたが見つけたように。

私は2つのオプションを考えることができます:

  1. は単に$(error)ものを削除します。 testが失敗すると、0以外の終了ステータスが返され、その時点でMakeプロセスが終了します。

  2. ルールのうち、テストを取り、そして、(順番にシェル機能を呼び出した)条件付きに使用例:

    ifeq ($(shell test -d /foobar; echo $$?),1) 
    $(error Not a directory) 
    endif 
    
+0

ありがとうございました。あなたの最初の提案はうまくいきます( 'if!test -d/foobar; then echo/foobarはディレクトリではありません; exit 1; fi')。有効なディレクトリでは、エラーは依然として発生しています。 –

0

なぜあなただ​​けの代わりにexit 1シェルコマンドを使用していません$(error ...)?後者を使用する理由はありますか?

try_this: 
    @test -d /foobar || { echo /foobar is not a directory; exit 1; } 

or_this: 
    @if [ ! -d /foobar ]; then echo /foobar is not a directory; exit 1; fi 

-k flagが指定されていない限り、これらの両方がmakeプロセスを中断します。

-k --keep-going

エラーの後、可能な限り続けます。失敗したターゲットとそれに依存するターゲットは再作成できませんが、これらのターゲットのその他の前提条件はすべて同じように処理できます。

+0

私は 'test -d'が両方で利用可能であったという誤った考えのもとで、cmdシェル/ sh移植性を窓口で撮影していました。しかし、私はまだ条件付きで$(エラー...)を呼び出す正しい方法に興味があります。 –

5

メイクレシピのシェルコマンドは、効果的に単一の再帰的に展開された変数として格納されます。 makeがレシピを実行することを決定した時点で、変数を展開し、各行を独自のシェル呼び出しで実行します。 $(error ...)が展開されると、最初のコマンドを呼び出す前にのmakeが中止されます。

$(if ...)または$(or ...) &cの未処理ブランチがあります。拡張されません。したがって、あなたはrealpath/末尾こと

.PHONY: rule-with-assert 
rule-with-assert: 
    $(if $(realpath ${should-be-file}/),$(error Assertion failure: ${should-be-file} is a folder!)) 
    ⋮ 

注意を行うことができます。

もちろん、マクロはこれをたくさん整理するのに役立ちます。

assert-is-file = $(if $(realpath $1/),$(error Assertion failure: [$1] is a folder!)) 

.PHONY: rule-with-assert 
rule-with-assert: 
    $(call assert-is-file,${should-be-file}) 
    ⋮ 

それはあなたがレシピに$(call assert-is-file,…)をどこに置いたか、それは問題ではないことを改めて注目に値します。 $(error)は、 の前にのシェルコマンドが実行される前にレシピが展開されると生成されます。

関連する問題