12

$(error ...)特定の前提条件が満たされない場合、make プロセスを中止するために使用したいと思います。失敗した場合、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)

$ make -f BAD.mk

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

ご覧のとおり、「エラーが機能しません...」でさえ画面にエコーされません。のレシピは、fails_to_work開始する前に失敗します。これを解決するにはどうすればよいですか?私の使用例の 1 つは ですが@test -d $(MY_ENV_VAR)、例に示されているハードコードされたパスと異なるとは思いません。

UPDATE(バージョン情報)

$ make --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
4

3 に答える 3

11

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

ただし、a$(if ...)または$(or ...)&cのアンテイクブランチに注意してください。展開されません。したがって、あなたはすることができます

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

/の末尾に注意してくださいrealpath

もちろん、マクロはこれを大いに片付けるのに役立ちます。

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)、レシピが展開されるときに すべてが生成されます。

于 2013-02-28T13:30:50.427 に答える
10

レシピでシェルのものを取得して、条件付きでメイクファイルのものを呼び出そうとしていますが、これは機能しません。

次の 2 つのオプションが考えられます。

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

  2. ルールからテストを取り出し、Make 条件 (シェル機能を呼び出す) を使用します。次に例を示します。

    ifeq ($(shell test -d /foobar; echo $$?),1)
    $(error Not a directory)
    endif
    
于 2012-06-18T20:05:08.397 に答える
3

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

-kflagが指定されていない限り、これらは両方とも make プロセスを中止します。

-k --keep-going

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

于 2012-06-18T21:23:18.137 に答える