2017-02-17 18 views
1

に私は「shell」機能を作成し、「$$」との間の差によって困惑しています。ドキュメントでは私が見つける:

シェル関数は(すべての引数のように)拡大し、実行するためにサブシェルに渡される単一の引数を受け入れます。コマンドの標準出力が読み込まれ、関数の値として返されます。

私は、これは同様にやっていた正確何 "$$" だと信じていたが、この小さな例では:

a = $(shell find . -maxdepth 1 -type f -name "Makefile") 
b = $$(find . -maxdepth 1 -type f -name "Makefile") 

.PHONY: all A B 

all: A B 

A: $(a) 
    @echo "Target: $(@)" 
    @echo "Prereq: $(<)" 
    @echo "Var a: $(a)" 
    @echo "Var b: $(b)" 

B: $(b) 
    @echo "Target: $(@)" 
    @echo "Prereq: $(<)" 
    @echo "Var a: $(a)" 
    @echo "Var b: $(b)" 

出力は次のようになります。

Target: A 
Prereq: Makefile 
Var a: ./Makefile 
Var b: ./Makefile 
make: *** No rule to make target '$(find)', needed by 'B'. Stop. 

注意ここでは、引数がまだ展開されていないかのように、「のターゲットを作成するルールはありません。 '(Find)'」となっています。 (変数を単純に展開するようにも試みましたが、 "b:=$$(...)"が、これは何も変わりませんでした)。

は、私は誰かが私には微妙な違いのように思えるよりこれについて詳しく説明するための知識を、持っていますが、おそらく私は、この時点で理解することができるよりもはるかに深遠であることを願っています。

答えて

2

$(shell ...)は、メイクテキスト機能です。置換時にあなたの例では、afindコマンドの結果に、拡大していきますので、これを拡大していきますしてください。 (単純拡張された変数を作成した場合、シェルコマンドはもちろん1回だけ評価されます)。

$$はちょうど$に展開されているので、あなたの例では、bは値$(find . -maxdepth 1 -type f -name "Makefile")として代用します。 b=または:=で定義されているかどうかは同じです。あなたはコマンドで$(b)を使用する場合

などecho $(b)として、コマンドシェルの実行は、コマンド置換としてこれが表示されます。つまり、シェルコマンドとしてecho $(find ...)があります。メイクのターゲットや依存関係に$(b)を使用して

は、あなたが見てきたように、それ以上の評価を行うませません。

もう1つの例のMakefileがあります。これは何が起きているかを示しています。私たちは、シェルが指定されている、文字通り何を示すために、単一引用符を使用します。

a = $$(echo true) 
b = $(shell echo true) 

print: 
    echo '$$a: $a' = "$a" 
    echo '$$b: $b' = "$b" 

.PHONY: print 

中のに対し、これは、私の最初のケースでは、シェルはそのコマンドで$(echo true)を与えていることを示す

echo '$a: $(echo true)' = "$(echo true)" 
$a: $(echo true) = true 
echo '$b: true' = "true" 
$b: true = true 

を与えます2番目のケースでは、Makeはecho trueを評価し、単に結果にtrueを代入します。

+0

徹底的な回答をいただきありがとうございます。この例は優れています。私はmakeがどのように変数を拡張するかは、いつも私にとってやや魔法的であると認めなければなりません。 –