60286


AWS の cli を叩いて、リソースがない場合に作成みたいなことを Makefile の中でやりたいです

シェル変数でも Makefile の変数でもいいのですが  
以下のようなテストコマンドをいろいろかいてみたんですがどうやっても空文字にマッチするIF文に入ってくれません

  1. シェル変数を使う場合

[code]

    test1:
        export A=1
        echo $A
    
[/code]

エクスポートしても別の行でとり出せない

[code]

    #make test1
    export A=1
    echo
    
[/code]

  2. eval のテスト

[code]

    test2:
        $(eval A := 1)
        echo $(A)
    ifeq (A, "")
        $(eval A := 2)
    endif
        echo $(A)
    
[/code]

これは正常

[code]

    #make test2
    echo 1
    1
    echo 1
    1
    
[/code]

3〜5. 実際に判定してほしいコマンド （違いは ifeq 文のみです)

[code]

    test3:
        $(eval A := $(shell aws apigateway get-rest-apis | jq -r '.items[] | select(.name=="test") | .id')))
        echo $(A)
    ifeq (A, "")
        $(eval A := 2)
    endif
        echo $(A)
    
    test4:
        $(eval A := $(shell aws apigateway get-rest-apis | jq -r '.items[] | select(.name=="test") | .id')))
        echo $(A)
    ifeq ("A", "")
        $(eval A := 2)
    endif
        echo $(A)
    
    test5:
        $(eval A := $(shell aws apigateway get-rest-apis | jq -r '.items[] | select(.name=="test") | .id')))
        echo $(A)
    ifeq ($(A), "")
        $(eval A := 2)
    endif
        echo $(A)
    
[/code]

どれも api-gateway が定義されてない場合空文字になって  
最後に 2 になってほしいのにならない

[code]

    #make test3
    echo
    
    echo
    
    #make test4
    echo
    
    echo
    
    #make test5
    echo
    
    echo
    
    
[/code]

どうすればコマンド結果が空かどうかを判定できるでしょうか

もっと根本的に Makefile 内で  
aws cli の結果によってリソースを作成するという簡単な方法があったりするでしょうか

make のバージョンは以下です

[code]

    # make -v
    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 i386-apple-darwin11.3.0
    
[/code]

参考： <http://quruli.ivory.ne.jp/document/make_3.79.1/make-
jp_6.html#Conditionals>

### 追記：

コメントで教えていただいたリンク先を参照して

[code]

    test6:
        $(eval A := $(shell aws apigateway get-rest-apis | jq -r '.items[] | select(.name=="test") | .id'))
        echo $(A)
    ifeq ($(A),)
        $(eval A := 2)
    endif
        echo $(A)
    
[/code]

という書き方を試したところ

[code]

    # make test6
    echo
    
    echo 2
    2
    
[/code]

と IF に入ってくれたのですが

逆に空文字以外でも必ず IF 文にマッチしてしまいます

[code]

    test7:
        $(eval A := 1)
        echo $(A)
    ifeq ($(A),)
        $(eval A := 2)
    endif
        echo $(A)
    
[/code]

[code]

    #make test7
    echo 1
    1
    echo 2
    2
    
[/code]

どこか書き方がまずいのでしょうか


CC BY-SA 4.0
2019-11-05T11:16:15.570
60277
2019-11-06T04:20:14.823
2019-11-06T02:38:57.667
question
shellscript makefile
Makefile で実行時にコマンド結果が空かどうか判定したい


コメントにも書きましたが、`ifeq` ディレクティブが Makefile の読み込み時に評価されてしまう事が原因です。

解決策の一つとして、[target-specific
variable](https://www.gnu.org/software/make/manual/html_node/Target_002dspecific.html)
を使う方法が考えられます。

[code]

    test6: \
        _ := $(shell aws apigateway get-rest-apis | jq -r '.items[] | select(.name=="test") | .id')
    test6: A := $(if $(_),$(_),2)
    
    test6:
        echo $(A)
    
[/code]

ただし、この場合は変数を global scope で定義しているので、他の recipe を実行する場合でも `aws apigateway ...`
コマンドが常に実行される事になります。`define` ディレクティブで別個に定義しておいて、recipe の実行時に `call`
する方が良いかもしれません。

と、書いておいて気が付いたのですが、以下の様にできますね。

[code]

    test6:
        $(eval _ := $(shell aws apigateway get-rest-apis | jq -r '.items[] | select(.name=="test") | .id' 2> /dev/null))
        $(eval A := $(if $(_),$(_),2))
        echo $(A)
    
[/code]


CC BY-SA 4.0
2019-11-06T03:41:43.973
60286
2019-11-06T03:49:58.123
2019-11-06T03:49:58.123
60277
answer


`ifreq` で変数が空文字列かどうかチェックするには、以下のいずれかのように書かないと駄目ですね。

[code]

    ifeq ($(A), )
    ...
    endif
    
[/code]

[code]

    EMPTY=
    ifeq ($(A), $(EMPTY))
    ...
    endif
    
[/code]

さて、自分だったらどうするかですが、こんな感じになりました。`Makefile` 中でもう一回 `make` を呼んでみました。AWS
のリソースではなくファイルを使い、なければ作っています。

[code]

    EMPTY:=
    A:=$(shell ls foo)
    
    .PHONY: default
    default: target
    
    .PHONY: target-pre
    target-pre:
        echo $@
    ifeq ($(A), $(EMPTY))
        touch foo
    endif
    
    .PHONY: target
    target: target-pre
        echo $@
        $(MAKE) target-do
    
    .PHONY: target-do
    target-do:
        echo $@
        ls -l foo
    
    .PHONY: clean
    clean:
        rm -f foo
    
[/code]


CC BY-SA 4.0
2019-11-06T04:20:14.823
60289
2019-11-06T04:20:14.823
3061
60277
answer