316

在我的makefile中,我有一个变量'NDK_PROJECT_PATH',我的问题是如何在编译时将其打印出来?

我读了Make file echo显示“$ PATH”字符串并尝试过:

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

两者都给我

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

任何人都知道为什么它对我不起作用?

4

15 回答 15

280

You can print out variables as the makefile is read (assuming GNU make as you have tagged this question appropriately) using this method (with a variable named "var"):

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

You can add this construct to any recipe to see what make will pass to the shell:

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

Now, what happens here is that make stores the entire recipe ($(info $$var is [${var}])echo Hello world) as a single recursively expanded variable. When make decides to run the recipe (for instance when you tell it to build all), it expands the variable, and then passes each resulting line separately to the shell.

So, in painful detail:

  • It expands $(info $$var is [${var}])echo Hello world
  • To do this it first expands $(info $$var is [${var}])
    • $$ becomes literal $
    • ${var} becomes :-) (say)
    • The side effect is that $var is [:-)] appears on standard out
    • The expansion of the $(info...) though is empty
  • Make is left with echo Hello world
    • Make prints echo Hello world on stdout first to let you know what it's going to ask the shell to do
  • The shell prints Hello world on stdout.
于 2013-05-10T19:19:33.990 回答
251

根据GNU Make 手册以及以下答案中的“bobbogo”所指出的,您可以使用info / warning / error来显示文本。

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

要打印变量,

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

'error' 将在显示错误字符串后停止执行

于 2015-04-17T16:23:51.323 回答
161

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

Add the following rule to your Makefile:

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

Then, if you want to find out the value of a makefile variable, just:

make print-VARIABLE

and it will return:

VARIABLE = the_value_of_the_variable
于 2014-09-12T22:12:53.660 回答
50

如果你只是想要一些输出,你想自己使用$(info)。您可以在 Makefile 中的任何位置执行此操作,它会在评估该行时显示:

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

VAR="<value of VAR>"每当 make 处理该行时都会输出。此行为非常依赖于位置,因此您必须确保$(info)扩展发生在所有可以修改的内容$(VAR)都已经发生之后!

一个更通用的选项是创建一个特殊的规则来打印变量的值。一般来说,规则是在分配变量后执行的,因此这将显示实际使用的值。(虽然,规则可以更改变量。)良好的格式将有助于阐明变量的设置,并且该$(flavor)函数会告诉您某物是什么类型的变量。所以在这条规则中:

print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
  • $*扩展为% 模式在规则中匹配的词干。
  • $($*)扩展为名称由 by 给出的变量的值$*
  • 并清楚地描绘了变量扩展[]您也可以使用"and"或类似的。
  • $(flavor $*)告诉你它是什么类型的变量。注意:$(flavor) 需要一个变量name,而不是它的扩展。所以如果你说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/...]
于 2015-12-13T19:15:53.460 回答
10

所有版本的make命令行都需要缩进 TAB(不是空格)作为行中的第一个字符。如果您向我们展示了整个规则,而不仅仅是有问题的两行,我们可以给出更清晰的答案,但应该是这样的:

myTarget: myDependencies
        @echo hi

其中第二行的第一个字符必须是 TAB。

于 2013-05-09T23:35:43.990 回答
8

@echo $(NDK_PROJECT_PATH) 是这样做的好方法。我不认为错误来自那里。通常,当您输入错误的意图时会出现此错误:我认为您应该有一个选项卡的空格。

于 2013-05-09T17:45:31.433 回答
6

无需修改 Makefile。

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

$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE
于 2018-02-14T07:49:28.557 回答
4

运行make -n;它向您显示变量的值..

生成文件...

all:
        @echo $(NDK_PROJECT_PATH)

命令:

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

输出:

echo /opt/ndk/project
于 2014-08-12T23:12:23.787 回答
3

makefile将生成“缺少分隔符”错误消息:

all
    @echo NDK_PROJECT_PATH=$(NDK_PROJECT_PATH)

done:
        @echo "All done"

之前有一个标签@echo "All done"(尽管done:规则和操作在很大程度上是多余的),但在@echo PATH=$(PATH).

问题是行开头all应该有一个冒号:或一个等号=来表示它是一个目标行或一个宏行,而它都没有,所以缺少分隔符。

回显变量值的操作必须与目标相关联,可能是虚拟目标或 PHONEY 目标。并且该目标行上必须有一个冒号。如果您在示例中添加:after并将下一行的前导空格替换为制表符,它将正常工作。allmakefile

您可能在原始的 102 行附近有类似的问题makefile。如果您在失败的回显操作之前显示 5 个非空白、非注释行,则可能完成诊断。但是,由于该问题是在 2013 年 5 月提出的,因此makefile现在(2014 年 8 月)损坏的不太可能仍然可用,因此无法正式验证此答案。它只能用于说明问题发生的合理方式。

于 2014-08-12T23:28:59.827 回答
3

问题是 echo 只能在执行块下工作。即“xx:”之后的任何内容

因此,第一个执行块之上的任何内容都只是初始化,因此不能使用执行命令。

所以创建一个执行块

于 2015-12-04T17:56:56.123 回答
2

如果不想修改 Makefile 本身,可以使用--eval添加新目标,然后执行新目标,例如

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

您可以使用在命令行中插入所需的 TAB 字符CTRL-V, TAB

上面的示例 Makefile:

all: do-something

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

do-something:
        @echo "doing something"
        @echo "running tests $(TESTS)"
        @exit 1
于 2017-02-20T18:38:36.797 回答
1

这可以通过通用方式完成,并且在调试复杂的 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
于 2016-05-18T13:57:08.450 回答
0

如果我想查看变量值,我通常会报错。(仅当您想查看该值时。它将停止执行。)

@echo $(错误 NDK_PROJECT_PATH= $(NDK_PROJECT_PATH))

于 2019-06-13T07:28:35.330 回答
0

如果您使用 android make (mka)@echo $(NDK_PROJECT_PATH)将不起作用并给您错误,如果您尝试在 android make 中打印变量,请*** missing separator. Stop." 使用此答案

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

对我有用

于 2017-03-18T05:18:14.673 回答
-1

您可以在 make 文件中创建一个 vars 规则,如下所示:

dispvar = echo $(1)=$($(1)) ; echo

.PHONY: vars
vars:
    @$(call dispvar,SOMEVAR1)
    @$(call dispvar,SOMEVAR2)

这里有一些更强大的方法来转储所有变量:gnu make: list the values of all variables (or "macros") in a specific run

于 2014-12-31T00:33:14.877 回答