私のメークファイルには、変数 'NDK_PROJECT_PATH'があります。私の質問は、コンパイル時にそれをどのように出力することができるかということです。
ファイルエコーに "$ PATH"という文字列を表示させます そして試してみました。
@echo $(NDK_PROJECT_PATH)
@echo $(value NDK_PROJECT_PATH)
どちらも私にくれます
"build-local.mk:102: *** missing separator. Stop."
なぜそれが私のために働いていないのか誰かが知っていますか?
この方法で( "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...)
の展開は空ですecho Hello world
のままです。echo Hello world
を印刷して、シェルに何を要求するのかを知らせますHello world
を出力します。"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
上記の回答の '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の実行が停止します。
単に何らかの出力が欲しいのなら、$(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/...]
make
のすべてのバージョンは、コマンドラインが行の最初の文字としてTAB(スペースではなく)でインデントされることを要求します。問題となっている2行だけではなく、ルール全体を見せていただければ、より明確な答えを出すことができますが、次のようになります。
myTarget: myDependencies
@echo hi
2行目の最初の文字はTABでなければなりません。
@echo $(NDK_PROJECT_PATH)がそれを実行するための良い方法です。私はエラーがそこから来るとは思わない。一般的にこのエラーはあなたが意図を誤入力したときに現れます:私はあなたがタブを持っているべきところにスペースがあると思います。
make -n
を実行してください。変数の値が表示されます。
Makefile ...
all:
@echo $(NDK_PROJECT_PATH)
コマンド:
export NDK_PROJECT_PATH=/opt/ndk/project
make -n
出力:
echo /opt/ndk/project
このmakefile
は、 'missing separator'エラーメッセージを生成します。
all
@echo NDK_PROJECT_PATH=$(NDK_PROJECT_PATH)
done:
@echo "All done"
@echo "All done"
の前にはタブがありますが(done:
のルールとアクションはほとんど不要ですが)、@echo PATH=$(PATH)
の前にはありません。
問題は、all
で始まる行にはコロン:
または等しい=
のどちらかがターゲット行またはマクロ行であることを示すためにあり、どちらもないため、区切り文字がないことです。
変数の値をエコーするアクションは、ターゲット、おそらくダミーターゲットまたはPHONEYターゲットに関連付ける必要があります。そしてそのターゲットラインはそれの上にコロンがなければなりません。例のall
のmakefile
の後に:
を追加し、次の行の先行ブランクをタブで置き換えた場合、それは問題なく機能します。
あなたはおそらくオリジナルのmakefile
の102行近くで同様の問題を抱えているでしょう。失敗しているエコー操作の前に5つの非ブランク、非コメント行を表示した場合は、おそらく診断を終了することが可能です。しかし、2013年5月に質問されたので、壊れたmakefile
がまだ利用可能であるとは考えにくいので(2014年8月)、この答えを正式に検証することはできません。問題が発生したもっともらしい方法を説明するためにのみ使用できます。
問題は、echoが実行ブロックの下でのみ機能することです。すなわち "xx:"の後にあるもの
したがって、最初の実行ブロックより上のものは初期化にすぎず、実行コマンドは使用できません。
実行ブロックを作成する
Makefileを修正する必要はありません。
$ cat printvars.mak
print-%:
@echo '$*=$($*)'
$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE
これは一般的な方法で行うことができ、複雑なメークファイルをデバッグするときに非常に役立ちます。 もう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
変数の値を表示するには、次のようにします。
rule:
<tab>@echo $(VAR_NAME)
ルールが実行されると、変数が表示されます。
android make(mka)を使用すると@echo $(NDK_PROJECT_PATH)
は機能せず、エラーになります*** missing separator. Stop."
use この答え Android makeで変数を印刷しようとしている場合
NDK_PROJECT_PATH := some_value
$(warning $(NDK_PROJECT_PATH))
それは私のために働いた
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
変数の値を表示したい場合、通常エラーでエコーします(値を表示したい場合のみ。実行を停止します)。
@echo $(エラーNDK_PROJECT_PATH = $(NDK_PROJECT_PATH))