Command line 如何从命令行将参数传递给Makefile?

Command line 如何从命令行将参数传递给Makefile?,command-line,parameters,makefile,arguments,Command Line,Parameters,Makefile,Arguments,如何从命令行将参数传递给Makefile 我知道我能做到 $ make action VAR="value" $ value 使用Makefile VAR = "default" action: @echo $(VAR) 如何获得以下行为 $ make action value value ? 怎么样 $make action value1 value2 value1 value2 你可能不应该这样做;你打破了Make工作的基本模式。但这是: action: @e

如何从命令行将参数传递给Makefile

我知道我能做到

$ make action VAR="value"
$ value
使用
Makefile

VAR = "default"
action:
    @echo $(VAR)
如何获得以下行为

$ make action value
value
?

怎么样

$make action value1 value2
value1 value2

你可能不应该这样做;你打破了Make工作的基本模式。但这是:

action:
        @echo action $(filter-out $@,$(MAKECMDGOALS))

%:      # thanks to chakrit
    @:    # thanks to William Pursell
编辑:
为了解释第一个命令

$(MAKECMDGOALS)
是命令行中列出的“目标”列表,例如“操作值1值2”

$@
表示规则目标的名称,在本例中为“操作”

filter out
是一个从列表中删除某些元素的函数。所以
$(过滤掉bar,foo bar baz)
返回
foo baz
(它可能更微妙,但我们不需要细节)


将它们放在一起,
$(过滤掉$@,$(MAKECMDGOALS))
返回命令行上指定的目标列表,而不是“action”,它可能是“value1 value2”。

执行此操作要容易得多。考虑一个任务:

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=“构建资产”制定准备金

或者只是:


make provision
在这种情况下,
AT
是一个空字符串

这里是一个基于@Beta的通用工作解决方案

我正在使用GNU Make 4.1,在我的Make文件上加上
SHELL=/bin/bash
,所以YMMV

这允许我们接受额外的参数(当我们得到一个不匹配的作业时不做任何事情,而不是抛出一个错误)

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

args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}`
这里有一个工作可以称之为:

test:
    @echo $(call args,defaultstring)
结果将是:

$ make test
defaultstring
$ make test hi
hi
注意!您最好使用“Taskfile”,这是一种bash模式,其工作原理与make类似,只是没有Maketools的细微差别。请参见

不要尝试这样做

$ make action value1 value2
而是创建脚本:

#! /bin/sh
# rebuild if necessary
make
# do action with arguments
action "$@"
这样做:

$ ./buildthenaction.sh value1 value2

要了解更多关于为什么要这样做以及makefile hackery的注意事项,请阅读我对另一个非常类似但似乎不重复的问题的回答:

几年后,想建议
仅此:


<代码> $(shell回声$(MAKECDMSTAILL)SED的!^ *$@!!)<代码>省略之前的所有目标,只考虑下面的参数:<代码>使Trave1 Talk2 ActudieValue2原谅我的无知。我试过用谷歌搜索
%:
@:
,但找不到关于这些“指令”(或它们被称为什么)的信息。你能解释一下吗?@Jon:手册上写着。由
%:
@:
组成的部分是一个。目标名称
%
表示它是;也就是说,如果Make找不到任何其他方法来构建您告诉它要构建的东西,它将执行该规则。
@:
是一个;
表示什么也不做,
@
表示默默地做。谢谢。我一直在阅读该手册,起初我没有考虑过,<>代码> %:<代码>实际上是代码> %:<代码>,通配符类型的目标名。我在手册中没有看到任何关于
@:
的内容,但是。。。它确实表明“什么也不做”规则只会有一个
在目标规范之后,那么,编写
%不是更准确吗
作为“通配符不执行任何操作”规则?
筛选出
在操作是命令行上指定的目标的依赖项时不起作用,因为
$@
将设置为依赖项的名称,而不是命令行上调用的原始参数。相反,我将
MAKECMDGOALS
分配给shell数组,然后删除第一个元素:
@args=($(MAKECMDGOALS));args=(“$${args[@]:1}”)
类似:它可能重复工作!!对于其他尝试此操作的人,请确保在
@echo
之前有
选项卡,而不是
空格
。如果操作(例如test:)是命令行上指定的目标的依赖项,则此操作也有效。
$ ./buildthenaction.sh value1 value2
action v1 v2=default:
    @echo 'take action on {{v1}} and {{v2}}...'