web-dev-qa-db-ja.com

メイクファイル変数の初期化とエクスポート

somevar := Apple
export somevar
update := $(Shell echo "v=$$somevar")

all:
    @echo $(update)

コマンドの出力としてAppleを望んでいましたが、それは空です。エクスポートと:=さまざまなフェーズで行われる変数の展開。これを克服する方法は?

31
Pablo

問題は、exportが変数をコマンドで使用されるサブシェルにエクスポートすることです。他の割り当ての拡張には使用できません。ルール外の環境から取得しようとしないでください。

somevar := Apple
export somevar

update1 := $(Shell Perl -e 'print "method 1 $$ENV{somevar}\n"')
# Make runs the Shell command, the Shell does not know somevar, so update1 is "method 1 ".

update2 := Perl -e 'print "method 2 $$ENV{somevar}\n"'
# Now update2 is Perl -e 'print "method 2 $$ENV{somevar}\n"'

# Lest we forget:
update3 := method 3 $(somevar)

all:
    echo $(update1)
    $(update2)
    echo $(update3)
    Perl -e 'print method 4 "$$ENV{somevar}\n"'
33
Beta

メイクファイルを実行する

foo:=Apple
export foo
all:
        @echo ">"$(Shell echo "$$foo")
        @echo ">""$$foo"

私に与えます(環境で未定義のfooを使用)

$ make
>
>Apple

$ make foo=bar
>
>Apple

$ export foo=bar; make
>bar
>Apple

$ export foo=bar; make foo=bar
>bar
>bar

引用形式(update := "v=$$somevar")コマンドの実行時にシェルが展開を処理できるようにします(エクスポートが必要です)

10
Scott Wales

export$(Shell ...)とうまく動作しませんが、簡単な回避策があります。コマンドライン経由でシェルスクリプトにデータを渡すことができます。

もちろん、環境の通過はエスケープとクォートの問題に対して堅牢です。ただし、シェル言語には、すべてを処理する一重引用符のクォートメソッド'...'があります。唯一の問題は、そこに単一引用符を取得する方法がないことです。もちろん、引用符を終了し、必要な単一引用符をバックスラッシュでエスケープし、新しい引用符を開始することで解決します。つまり、

ab'cd -> 'ab'\''cd'

$(Shell ...)によって実行されるシェルスクリプトでは、var='$(...)'という形式の変数割り当てを生成します。$(...)は、適切にエスケープされたマテリアルを補間するmake式です。したがって、Makefile

somevar := Apple with 'quoted' "stuff" and dollar $$signs

Shell_escape = $(subst ','\'',$(1))

update := $(Shell v='$(call Shell_escape,$(somevar))'; echo $$v > file.txt)

.phony: all

all:
    cat file.txt

サンプル実行:

$ make
cat file.txt
Apple with 'quoted' "stuff" and dollar $signs

環境変数をコマンドに伝えたい場合は、シェル構文VAR0=val0 VAR1=val1 ... VARn=valn command arg ...を使用してそれを行うことができます。これは、上記のMakefileにいくつかの小さな変更を加えることで説明できます。

somevar := Apple with 'quoted' "stuff" and dollar $$signs

Shell_escape = $(subst ','\'',$(1))

update := $(Shell somevar='$(call Shell_escape,$(somevar))' env > file.txt)

.phony: all

all:
        grep somevar file.txt

実行:

$ make
grep somevar file.txt
somevar=Apple with 'quoted' "stuff" and dollar $signs

file.txtには、somevarを確認できる環境変数のダンプが含まれています。 export in GNU Makeが正しいことをすれば、次のことができるようになります。

export somevar
update := $(Shell env > file.txt)

しかし、最終結果は同じです。

最終結果はecho $(update)であるため、GNU渡されたエクスポート変数を$(Shell ...)に渡す場合でも] Shell_escapeになります。言うには、もう1つMakefileを見てください。

somevar := Apple with 'quoted' "stuff" and dollar $$signs

Shell_escape = $(subst ','\'',$(1))

update := $(Shell v='$(call Shell_escape,$(somevar))'; echo $$v)

.phony: all

all:
    @echo '$(call Shell_escape,$(update))'
    @echo $(update)

出力:

Apple with 'quoted' "stuff" and dollar $signs
Apple with quoted stuff and dollar
1
Kaz