How to pass argument to Makefile from command line?
如何从命令行将参数传递给makefile?
我知道我能做到
1 2
| $ make action VAR="value"
$ value |
与Makefile一起
1 2 3
| VAR ="default"
action:
@echo $(VAR) |
如何获得以下行为?
1 2
| $ make action value
value |
?
怎么样
1 2
| $make action value1 value2
value1 value2 |
- 类似:向"make run"传递参数
- 向"make run"传递参数的可能重复项
你可能不应该这样做;你正在打破制造工作的基本模式。但这里是:
1 2 3 4 5
| action:
@echo action $(filter-out $@,$(MAKECMDGOALS))
%: # thanks to chakrit
@: # thanks to William Pursell |
编辑:为了解释第一个命令,
$(MAKECMDGOALS)是命令行中列出的"目标"列表,例如"action value1 value2"。
$@是规则目标名称的自动变量,在本例中为"action"。
filter-out是从列表中删除某些元素的函数。因此,$(filter-out bar, foo bar baz)返回foo baz(它可能更微妙,但我们不需要在这里微妙)。
把它们放在一起,$(filter-out $@,$(MAKECMDGOALS))返回命令行上指定的目标列表,而不是"action",它可能是"value1 value2"。
- 我不知道是因为你聪明而反对你,还是因为你精神错乱而反对你。我要投赞成票。
- 你能解释一下$(filter-out $@,$(MAKECMDGOALS))是怎么做的吗?
- 但这只在你事先知道字符串value1和value2的情况下有效,对吗?如果这是一个任意的论点呢?
- @查克里特:你说得对。我会修改的…
- $(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')省略前面的所有目标,并将以下内容作为论据:make target1 target2 action value1 value2。
- 请原谅我的无知。我试过用google搜索%:和@:,但找不到这些"指令"(或它们的名字)的信息。你能解释一下吗?
- @乔恩:手册在这里。由%:和@:组成的部分是一个规则。目标名称%意味着它是一个匹配任何内容的规则;也就是说,如果make找不到任何其他方法来构建您告诉它要构建的内容,它将执行该规则。@:是一个配方;:意味着什么都不做,@意味着安静地做。
- 谢谢。我一直在阅读手册,起初我没有考虑到%:实际上是% :,一个通配符类型的目标名称。不过,我在手册中没有看到关于@:的任何内容……它确实建议"不做任何事情"规则在目标规范之后只具有一个;,那么,将% : ;编写为"通配符不做任何事情"规则是否更准确?
- 当操作依赖于命令行上指定的目标时,filter-out不起作用,因为$@将被设置为依赖项的名称,而不是命令行上调用的原始参数。相反,我将MAKECMDGOALS分配给shell数组,然后删除第一个元素:@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")。
- fwiw,":"是"true"命令的同义词,可能不那么神秘。:"不再经常使用,而且简洁可能不值得……?
- @测试版使用您的解决方案(太棒了,哇)——您知道如何在执行结束时抑制输出,即,make: 'input1' is up to date用于各种输入吗?
- @测试版让我有90%的成功率,但如果我的arg是"le creuset",它将在空间上分裂,尽管被包裹着。这里有已知的解决方法吗?
下面是基于@beta的通用工作解决方案
我用的是GNUmake4.1和我的makefile上面的SHELL=/bin/bash,所以ymmv!
这允许我们接受额外的参数(当我们得到一个不匹配的任务时什么也不做,而不是抛出一个错误)。
这是一个宏,它为我们获取参数:
1
| args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}` |
这里有一个工作可以称之为:
1 2
| test:
@echo $(call args,defaultstring) |
结果是:
1 2 3 4
| $ make test
defaultstring
$ make test hi
hi |
注意!您最好使用"taskfile",它是一种bash模式,工作原理与make类似,只是没有maketools的细微差别。请参阅https://github.com/adriancooney/taskfile
- 它奏效了!!对于其他人来说,确保在@echo之前有tab,而不是space。
从我的角度来看,做一些像下面的示例这样的事情要容易得多。考虑一项任务:
1 2 3 4 5 6
| provision:
ansible-playbook -vvvv \
-i .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory \
--private-key=.vagrant/machines/default/virtualbox/private_key \
--start-at-task="$(AT)" \
-u vagrant playbook.yml |
现在,当我想打电话给它的时候,我只需要运行如下的程序:
AT="build assets" make provision
或者只是:
make provision在这种情况下,AT是一个空字符串。