如何从命令行传递参数到Makefile?

Men*_* Lu 99 parameters command-line arguments makefile

如何从命令行传递参数到Makefile?

我明白我能做到

$ make action VAR="value"
$ value
Run Code Online (Sandbox Code Playgroud)

Makefile

VAR = "default"
action:
    @echo $(VAR)
Run Code Online (Sandbox Code Playgroud)

我如何获得以下行为?

$ make action value
value
Run Code Online (Sandbox Code Playgroud)

怎么样

$make action value1 value2
value1 value2
Run Code Online (Sandbox Code Playgroud)

Bet*_*eta 191

你可能不应该这样做; 你打破了Make如何运作的基本模式.但这里是:

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

%:      # thanks to chakrit
    @:    # thanks to William Pursell
Run Code Online (Sandbox Code Playgroud)

编辑:
解释第一个命令,

$(MAKECMDGOALS) 是命令行中拼写的"目标"列表,例如"action value1 value2".

$@是规则目标名称的自动变量,在本例中为"action".

filter-out是一个从列表中删除一些元素的函数.所以$(filter-out bar, foo bar baz)返回foo baz(它可能更微妙,但我们这里不需要微妙).

将它们放在一起并$(filter-out $@,$(MAKECMDGOALS))返回命令行中指定的目标列表,而不是"action",它可能是"value1 value2".

  • @Jon:手册是[这里](http://www.gnu.org/software/make/manual/make.html).由`%:`和`@:`组成的部分是[规则](http://www.gnu.org/software/make/manual/make.html#Rules).目标名称'%`表示它是[匹配任何内容的规则](http://www.gnu.org/software/make/manual/make.html#Match_002dAnything-Rules); 也就是说,如果Make无法找到任何其他方法来构建您要建立的东西,它将执行该规则.`@:`是[食谱](http://www.gnu.org/software/make/manual/make.html#Rule-Syntax); `:`意味着什么都不做,而`@`意味着默默地做. (13认同)
  • 原谅我的无知。我尝试过谷歌搜索“%:”和“@:”,但无法找到有关这些“指令”(或它们的名称)的作用的信息。您能解释一下吗? (4认同)
  • `$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')` 忽略之前的所有目标,只考虑以下参数:`make target1 target2 action value1 value2` (3认同)
  • “你正在打破 Make 工作方式的基本模式”——这是什么意思?什么是“正确”的模式? (3认同)
  • 当操作是命令行上指定的目标的依赖项时,“filter-out”不起作用,因为“$@”将设置为依赖项的名称,而不是命令行上调用的原始参数。相反,我将 `MAKECMDGOALS` 分配给 shell 数组,然后删除第一个元素:`@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")` (2认同)

M3D*_*M3D 10

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

SHELL=/bin/bash在Makefile上面使用GNU Make 4.1 ,所以YMMV!

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

%:
    @:
Run Code Online (Sandbox Code Playgroud)

这是一个宏,它为我们得到了args:

args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}`
Run Code Online (Sandbox Code Playgroud)

这是一个可能称之为的工作:

test:
    @echo $(call args,defaultstring)
Run Code Online (Sandbox Code Playgroud)

结果将是:

$ make test
defaultstring
$ make test hi
hi
Run Code Online (Sandbox Code Playgroud)

注意!使用"任务文件"可能会更好,这是一种类似于make的bash模式,只是没有Maketools的细微差别.请参阅https://github.com/adriancooney/Taskfile

  • 有效!!对于其他尝试它的人,请确保在 `@echo` 之前有 `tab`,而不是 `space`。 (2认同)
  • 如果 Makefile 中存在目标“hi”,这将执行该目标。知道如何避免这种情况吗? (2认同)

Ale*_*zel 10

几年后,想just为此提出建议:https://github.com/casey/just

action v1 v2=default:
    @echo 'take action on {{v1}} and {{v2}}...'
Run Code Online (Sandbox Code Playgroud)


kha*_*iuk 9

从我的角度来看,更容易做下面的示例.考虑一项任务:

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
Run Code Online (Sandbox Code Playgroud)

现在,当我想打电话时,我只是运行:

AT="build assets" make provision

要不就:

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


小智 6

您最好定义变量并调用 make 而不是使用参数:

生成文件

action: ## My action helper
    @echo $$VAR_NAME
Run Code Online (Sandbox Code Playgroud)

终端

> VAR_NAME="Hello World" make action
Hello World
Run Code Online (Sandbox Code Playgroud)