在我的makefile中,我有一个变量'NDK_PROJECT_PATH',我的问题是如何在编译时将其打印出来?
我读了Make file echo displaying "$PATH" string,我试过:
@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将传递给shell的内容:
.PHONY: all
all: ; $(info $$var is [${var}])echo Hello world
现在,这里发生的是将整个配方($(info $$var is [${var}])echo Hello world
)存储为单个递归扩展变量。当make决定运行配方时(例如,当你告诉它构建all
时),它会扩展变量,然后将每个结果行分别传递给shell。
所以,在痛苦的细节:
$(info $$var is [${var}])echo Hello world
$(info $$var is [${var}])
$$
成为字面上的$
${var}
成为:-)
(说)
副作用是$var is [:-)]
出现在标准输出上
尽管$(info...)
的扩张是空洞的echo Hello world
首先在stdout上打印echo Hello world
,让你知道它将要求shell做什么Hello world
。要打印变量的值,您可以使用:
rule:
<tab>@echo $(VAR_NAME)
当规则运行时,变量将被打印。
这可以通用方式完成,在调试复杂的makefile时非常有用。遵循another answer中描述的相同技术,您可以将以下内容插入到任何makefile中:
# 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
无需修改Makefile。
$ cat printvars.mak
print-%:
@echo '$*=$($*)'
$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE
如果您不想修改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
如果你使用android make(mka)@echo $(NDK_PROJECT_PATH)
将不起作用并给你错误*** missing separator. Stop."
使用this answer如果你试图在android make中打印变量
NDK_PROJECT_PATH := some_value
$(warning $(NDK_PROJECT_PATH))
这对我有用
如果我想查看变量值,我通常会回显一个错误。(只有当你想看到它时才会看到它。它会停止执行。)
@echo $(错误NDK_PROJECT_PATH = $(NDK_PROJECT_PATH))
来自“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,您可以使用信息/警告/错误来显示文本。
$(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)")
每当制作流程时输出VAR="<value of VAR>"
。这种行为是非常依赖于位置的,所以你必须确保$(info)
扩展发生在可能修改$(VAR)
的所有内容已经发生之后!
更通用的选项是创建用于打印变量值的特殊规则。一般来说,规则是在赋值变量后执行的,因此这将显示实际使用的值。 (虽然它是possible for a rule to change a variable。)良好的格式化将有助于澄清变量的设置,而$(flavor)
函数将告诉你什么类型的变量。所以在这条规则中:
print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
$*
扩展到%
模式在规则中匹配的词干。$($*)
扩展为变量的值,该变量的名称由$*
给出。[
和]
清楚地描述了变量扩张。你也可以使用"
和"
或类似的。$(flavor $*)
告诉你它是什么样的变量。注意:$(flavor)
采用变量名称,而不是其扩展名。所以,如果你说make print-LDFLAGS
,你得到$(flavor LDFLAGS)
,这是你想要的。$(info text)
提供输出。在其标准上打印text
作为扩展的副作用。 $(info)
的扩张虽然空洞。您可以将其视为@echo
,但重要的是它不使用shell,因此您不必担心shell引用规则。@true
只是为规则提供命令。没有它,make也将输出print-blah is up to date
。我觉得@true
更清楚地表明这是一个无操作。运行它,你得到
$ make print-LDFLAGS
LDFLAGS is a recursive variable set to [-L/Users/...]
@echo $(NDK_PROJECT_PATH)是做到这一点的好方法。我不认为错误来自那里。通常,当您输入错误时会出现此错误:我认为您有空格,您应该有一个标签。
所有版本的make
都要求使用TAB(而不是空格)缩进命令行作为行中的第一个字符。如果你向我们展示了整个规则而不仅仅是两条线,我们可以给出一个更清晰的答案,但它应该是这样的:
myTarget: myDependencies
@echo hi
第二行中的第一个字符必须是TAB。
运行make -n
;它显示了变量的值..
Makefile中...
all:
@echo $(NDK_PROJECT_PATH)
命令:
export NDK_PROJECT_PATH=/opt/ndk/project
make -n
输出:
echo /opt/ndk/project
此makefile
将生成“缺少分隔符”错误消息:
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:”之后的任何内容
因此,第一个执行块之上的任何内容都只是初始化,因此不能使用执行命令。
所以创建一个执行块