web-dev-qa-db-ja.com

Makefileの中の変数を表示する方法

私のメークファイルには、変数 'NDK_PROJECT_PATH'があります。私の質問は、コンパイル時にそれをどのように出力することができるかということです。

ファイルエコーに "$ PATH"という文字列を表示させます そして試してみました。

@echo $(NDK_PROJECT_PATH)
@echo $(value NDK_PROJECT_PATH)

どちらも私にくれます

"build-local.mk:102: *** missing separator.  Stop."

なぜそれが私のために働いていないのか誰かが知っていますか?

198
michael

この方法で( "var"という名前の変数を使用して)makefileを読み込むときに変数を出力できます(この質問に適切にタグ付けしたようにGNU makeを仮定)。

$(info $$var is [${var}])

この構文を任意のレシピに追加して、makeがシェルに渡す内容を確認できます。

.PHONY: all
all: ; $(info $$var is [${var}])echo Hello world

さて、ここで起こることはmakeがレシピ全体($(info $$var is [${var}])echo Hello world)を単一の再帰的に展開された変数として保存することです。 makeがレシピを実行することを決定したとき(たとえば、allを構築するように指示したとき)、変数を展開してから、結果の各行を別々にシェルに渡します。

だから、痛みを伴う詳細では:

  • $(info $$var is [${var}])echo Hello worldを展開します
  • これを行うには、まず$(info $$var is [${var}]) を展開します。
    • $$はリテラルになります$
    • ${var}:-)になります(say)
    • 副作用は$var is [:-)]が標準出力に現れることです
    • $(info...)の展開は空です
  • Makeはecho Hello world のままです。
    • 最初に標準出力にecho Hello worldを印刷して、シェルに何を要求するのかを知らせます
  • シェルは標準出力にHello worldを出力します。
187
bobbogo

"Mr. Make post"より https://www.cmcrossroads.com/article/printing-value-makefile-variable

Makefileに次のルールを追加してください。

print-%  : ; @echo $* = $($*)

それでは、makefile変数の値を調べたいのなら、

make print-VARIABLE

そしてそれは戻ります:

VARIABLE = the_value_of_the_variable
128

上記の回答の 'bobbogo'が指摘したように、そして GNU Make manual に従って、あなたはテキストを表示するためにinfo/warning/errorを使うことができます。

$(error   text…)
$(warning text…)
$(info    text…)

変数を印刷するには

$(error   VAR is $(VAR))
$(warning VAR is $(VAR))
$(info    VAR is $(VAR))

'error'を使用すると、エラー文字列を表示した後にmakeの実行が停止します。

125
tsenapathy

単に何らかの出力が欲しいのなら、$(info)を単独で使いたいのです。あなたはMakefileのどこでもそれをすることができます、そしてそれはその行が評価される時に表示されます:

$(info VAR="$(VAR)")

Makeがその行を処理するたびにVAR="<value of VAR>"を出力します。この振る舞いは非常に位置に依存するので、$(info)を変更する可能性のあるものがすべて起こった後に$(VAR)の展開が行われることを確認する必要があります。

より一般的なオプションは、変数の値を表示するための特別な規則を作成することです。一般的に言って、ルールは変数が割り当てられた後に実行されるので、これはあなたに実際に使われている値を示すでしょう。 (しかし、それは 変数を変更するルールで可能です です。)良いフォーマットは、変数が何に設定されるかを明確にするのに役立ちます、そして$(flavor)関数はどんな種類の変数かを教えてくれます。だからこのルールでは:

print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
  • $*は、% pattern がルール内で一致したという語幹に展開されます。
  • $($*)は、名前が$*で与えられる変数の値に展開されます。
  • []は変数展開を明確に表しています。 ""などを使うこともできます。
  • $(flavor $*)はどのような変数なのかを教えてくれます。注:$(flavor)は変数 name を取り、その展開は取りません。 make print-LDFLAGSと言うと、$(flavor LDFLAGS)が得られます。これがあなたが望むものです。
  • $(info text)は出力を提供します。 Make は展開の副作用としてtextを標準出力に表示します。 $(info)の展開は空です。あなたはそれを@echoのように考えることができます、しかし重要なことにそれはシェルを使用しないので、あなたはシェルの引用規則について心配する必要はありません。
  • @trueはルールのコマンドを提供するためだけにあります。それがなければ、 make print-blah is up to dateを出力します。私は@trueがそれがノーオペレーションであることを意味することをより明確にしていると感じます。

実行すると、

$ make print-LDFLAGS
LDFLAGS is a recursive variable set to [-L/Users/...]
39
Jim Nasby

makeのすべてのバージョンは、コマンドラインが行の最初の文字としてTAB(スペースではなく)でインデントされることを要求します。問題となっている2行だけではなく、ルール全体を見せていただければ、より明確な答えを出すことができますが、次のようになります。

myTarget: myDependencies
        @echo hi

2行目の最初の文字はTABでなければなりません。

6
MadScientist

@echo $(NDK_PROJECT_PATH)がそれを実行するための良い方法です。私はエラーがそこから来るとは思わない。一般的にこのエラーはあなたが意図を誤入力したときに現れます:私はあなたがタブを持っているべきところにスペースがあると思います。

5
user1746732

make -nを実行してください。変数の値が表示されます。

Makefile ...

all:
        @echo $(NDK_PROJECT_PATH)

コマンド:

export NDK_PROJECT_PATH=/opt/ndk/project
make -n 

出力:

echo /opt/ndk/project
4
ivandcl

このmakefileは、 'missing separator'エラーメッセージを生成します。

all
    @echo NDK_PROJECT_PATH=$(NDK_PROJECT_PATH)

done:
        @echo "All done"

@echo "All done"の前にはタブがありますが(done:のルールとアクションはほとんど不要ですが)、@echo PATH=$(PATH)の前にはありません。

問題は、allで始まる行にはコロン:または等しい=のどちらかがターゲット行またはマクロ行であることを示すためにあり、どちらもないため、区切り文字がないことです。

変数の値をエコーするアクションは、ターゲット、おそらくダミーターゲットまたはPHONEYターゲットに関連付ける必要があります。そしてそのターゲットラインはそれの上にコロンがなければなりません。例のallmakefileの後に:を追加し、次の行の先行ブランクをタブで置き換えた場合、それは問題なく機能します。

あなたはおそらくオリジナルのmakefileの102行近くで同様の問題を抱えているでしょう。失敗しているエコー操作の前に5つの非ブランク、非コメント行を表示した場合は、おそらく診断を終了することが可能です。しかし、2013年5月に質問されたので、壊れたmakefileがまだ利用可能であるとは考えにくいので(2014年8月)、この答えを正式に検証することはできません。問題が発生したもっともらしい方法を説明するためにのみ使用できます。

3

問題は、echoが実行ブロックの下でのみ機能することです。すなわち "xx:"の後にあるもの

したがって、最初の実行ブロックより上のものは初期化にすぎず、実行コマンドは使用できません。

実行ブロックを作成する

2
Andy

Makefileを修正する必要はありません。

$ cat printvars.mak
print-%:
        @echo '$*=$($*)'

$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE
1
Talespin_Kit

これは一般的な方法で行うことができ、複雑なメークファイルをデバッグするときに非常に役立ちます。 もう1つの答え に記載されているのと同じ手法に従って、次の行を任意のメイクファイルに挿入できます。

# if the first command line argument is "print"
ifeq ($(firstword $(MAKECMDGOALS)),print)

  # take the rest of the arguments as variable names
  VAR_NAMES := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))

  # turn them into do-nothing targets
  $(eval $(VAR_NAMES):;@:))

  # then print them
  .PHONY: print
  print:
          @$(foreach var,$(VAR_NAMES),\
            echo '$(var) = $($(var))';)
endif

それから、単に "make print"を実行して任意の変数の値をダンプすることができます。

$ make print CXXFLAGS
CXXFLAGS = -g -Wall
1
Idelic

変数の値を表示するには、次のようにします。

rule:
<tab>@echo $(VAR_NAME)

ルールが実行されると、変数が表示されます。

1
Samuel

android make(mka)を使用すると@echo $(NDK_PROJECT_PATH)は機能せず、エラーになります*** missing separator. Stop." use この答え Android makeで変数を印刷しようとしている場合

NDK_PROJECT_PATH := some_value
$(warning $(NDK_PROJECT_PATH))

それは私のために働いた

0
mjalil

Makefile自体を修正したくない場合は、--evalを使用して新しいターゲットを追加してから、その新しいターゲットを実行することができます。

make --eval='print-tests: @echo TESTS $(TESTS) ' print-tests

CTRL-V, TABを使用してコマンドラインに必要なTAB文字を挿入できます。

上記のMakefileの例:

all: do-something

TESTS=
TESTS+='a'
TESTS+='b'
TESTS+='c'

do-something:
        @echo "doing something"
        @echo "running tests $(TESTS)"
        @exit 1
0
Wade

変数の値を表示したい場合、通常エラーでエコーします(値を表示したい場合のみ。実行を停止します)。

@echo $(エラーNDK_PROJECT_PATH = $(NDK_PROJECT_PATH))

0
Abdul Jaleel