关于参数:如何从命令行向Makefile传递参数?

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


你可能不应该这样做;你正在打破制造工作的基本模式。但这里是:

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"。


下面是基于@beta的通用工作解决方案

我用的是GNUmake4.1和我的makefile上面的SHELL=/bin/bash,所以ymmv!

这允许我们接受额外的参数(当我们得到一个不匹配的任务时什么也不做,而不是抛出一个错误)。

1
2
%:
    @:

这是一个宏,它为我们获取参数:

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


从我的角度来看,做一些像下面的示例这样的事情要容易得多。考虑一项任务:

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是一个空字符串。