如何在makefile中打印出一个variables

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

我读取显示“$ PATH”string的文件回显 ,我试着:

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

两者都给我

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

任何人都知道为什么它不为我工作?

你可以使用这个方法(使用一个名为“var”的variables)读取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作为一个recursion的扩展variables存储。 当决定运行配方(例如当你告诉它build立all )时,它展开variables,然后将每条生成的线分别传递给shell。

所以,在痛苦的细节:

  • 它展开$(info $$var is [${var}])echo Hello world
  • 要做到这一点,它首先展开$(info $$var is [${var}])
    • $$变成文字$
    • ${var}变成:-)(说)
    • 副作用是$var is [:-)]出现在标准输出
    • $(info...)的扩展虽然是空的
  • Make留下echo Hello world
    • 首先让标记在标准输出中echo Hello world ,让你知道它将要求shell做些什么
  • shell在标准输出中打印Hello world

从“Mr. Make post” https://www.cmcrossroads.com/article/printing-value-makefile-variable

将以下规则添加到您的Makefile中:

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

那么,如果你想找出一个makefilevariables的值,只需:

 make print-VARIABLE 

它会返回:

 VARIABLE = the_value_of_the_variable 

正如上面答案中的“bobbogo”所指出的,按照GNU Make手册 ,您可以使用info / warning / error来显示文本。

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

要打印variables,

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

当你使用'错误'时,执行将显示错误string后停止

如果你只是想要一些输出,你想单独使用$(info) 。 您可以在Makefile中的任何位置执行此操作,并且会在计算该行时显示:

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

输出VAR="<value of VAR>"每当进行处理。 这种行为是非常依赖于位置的,所以你必须确保$(info)扩展发生在所有可能修改$(VAR)事情发生后!

更通用的select是创build打印variables值的特殊规则。 一般来说,规则是在variables被赋值之后执行的,所以这会告诉你实际使用的值。 (虽然规则可以改变一个variables 。)良好的格式将有助于澄清variables的设置,而$(flavor)函数会告诉你什么样的variables。 所以在这个规则中:

 print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true 
  • $*扩展到在规则中匹配% 模式的词干。
  • $($*)扩展为名称由$*给定的variables的值。
  • []清楚地描述了variables扩展。 你也可以使用""或类似的。
  • $(flavor $*)告诉你它是什么types的variables。 注意: $(flavor)需要一个variables名称 ,而不是其扩展名。 所以如果你说make print-LDFLAGS ,你会得到$(flavor LDFLAGS) ,这就是你想要的。
  • $(info text)提供输出。 在其stdout上打印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)是做这件事的好方法。 我不认为这个错误来自那里。 一般来说,这个错误出现在你打错input时:我认为你有空间,你应该有一个标签。

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

 myTarget: myDependencies @echo hi 

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

运行make -n ; 它显示了variables的值

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"之前有一个选项卡(尽pipedone:规则和动作在很大程度上是多余的),但不在@echo PATH=$(PATH)

麻烦的是, all开始的行应该有一个冒号:或等于=表示它是一个目标行或一个macros行,它没有,所以分隔符丢失。

响应variables值的动作必须与目标相关联,可能是虚拟或PHONEY目标。 那个目标行必须有冒号。 如果您在示例makefile添加了一个:在下一行中用标签replace前导空白,它将工作得很好。

在原始的makefile中,你可能在102行附近有类似的问题。 如果在回显操作失败之前显示5个非空白非注释行,则可能会完成诊断。 但是,自从2013年5月提出这个问题以来,破解的makefile不太可能现在(2014年8月)仍然可用,所以这个答案不能正式validation。 它只能用来说明问题发生的合理方式。

要打印variables的值,您可以使用:

 rule: <tab>@echo $(VAR_NAME) 

当规则运行时,variables将被打印。

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

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

所以创build一个执行团队

这可以通用的方式完成,并且在debugging复杂的makefile时非常有用。 按照另一个答案中所述的相同技术,可以将以下内容插入到任何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 

然后你可以做“打印”来转储任何variables的值:

 $ make print CXXFLAGS CXXFLAGS = -g -Wall 

如果你不想修改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." *** missing separator. Stop."如果你想在android make中打印variables,请使用这个答案

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

为我工作