Makefileにbash間接変数の割り当てを含める方法

Makefileにbash間接変数の割り当てを含める方法

Bashの間接変数の設定は、次のように実行できます。だから:

#!/bin/bash
foo=bar
ind=foo
echo ${!ind}   # prints `bar'

(GNU)Makefileレシピと同じように実行してみてください。

# Makefile
test:
    foo=bar
    ind=foo
    echo $$\{!ind\}
    echo $${!ind}

文字がエスケープされているかどうかにかかわらず、{}次のメッセージで失敗します。

foo=bar
ind=foo
echo $\{!ind\}
${!ind}
echo ${!ind}
/bin/sh: 1: Bad substitution
/tmp/Makefile:2: recipe for target 'test' failed
make: *** [test] Error 2

問題は、Makefileで特殊文字が欠落しているか、誤ってエスケープされている可能性があります。

あるいは、変数拡張の順序/タイミングであることもできます。Makeの2次拡張

どんなアイデアがありますか?

重要であれば、これはbash4.4.12(1)-releaseでmakeです。GNU Make 4.1

答え1

あなたは本当にすごいです。質問を投稿してから10分も経たないで、あなたは私に正しい解決策を案内してくれました。

# Makefile
SHELL=/bin/bash
test:
    foo=bar; \
    ind=foo; \
    echo $${!ind}

スチールドライバー、チョロバ様、ありがとうございます。

答え2

ここには2つの質問があります。

  1. レシピのデフォルトのシェルなので、同様の構文を理解するにはレシピをsh使用する必要があります。SHELL=/bin/bash${!ind}
  2. レシピの各行は別々のシェルによって実行されるため、レシピに変数を定義すると、同じレシピの次の行でその変数が失われます。これは.ONESHELL特別な目標によって解決されます。

したがって、実際の例は次のとおりです。

# Makefile
.ONESHELL:
SHELL=/bin/bash
test:
    foo=bar
    ind=foo
    echo $$\{!ind\}
    echo $${!ind}

より詳細な(そして正式な)説明については、次のサイトをご覧ください。 https://www.gnu.org/software/make/manual/make.html#Execution

関連情報