How to pass argument to Makefile from command line

2020-01-26 12:43发布

How to pass argument to Makefile from command line?

I understand I can do

$ make action VAR="value"
$ value

with Makefile

VAR = "default"
action:
    @echo $(VAR)

How do I get the following behavior?

$ make action value
value

?

How about

$make action value1 value2
value1 value2

4条回答
Viruses.
2楼-- · 2020-01-26 13:14

You probably shouldn't do this; you're breaking the basic pattern of how Make works. But here it is:

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

%:      # thanks to chakrit
    @:    # thanks to William Pursell

EDIT:
To explain the first command,

$(MAKECMDGOALS) is the list of "targets" spelled out on the command line, e.g. "action value1 value2".

$@ is an automatic variable for the name of the target of the rule, in this case "action".

filter-out is a function that removes some elements from a list. So $(filter-out bar, foo bar baz) returns foo baz (it can be more subtle, but we don't need subtlety here).

Put these together and $(filter-out $@,$(MAKECMDGOALS)) returns the list of targets specified on the command line other than "action", which might be "value1 value2".

查看更多
时光不老,我们不散
3楼-- · 2020-01-26 13:17

Here is a generic working solution based on @Beta's

I'm using GNU Make 4.1 with SHELL=/bin/bash atop my Makefile, so YMMV!

This allows us to accept extra arguments (by doing nothing when we get a job that doesn't match, rather than throwing an error).

%:
    @:

And this is a macro which gets the args for us:

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

Here is a job which might call this one:

test:
    @echo $(call args,defaultstring)

The result would be:

$ make test
defaultstring
$ make test hi
hi

Note! You might be better off using a "Taskfile", which is a bash pattern that works similarly to make, only without the nuances of Maketools. See https://github.com/adriancooney/Taskfile

查看更多
聊天终结者
4楼-- · 2020-01-26 13:18

don't try to do this

$ make action value1 value2

instead create script:

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

and do this:

$ ./buildthenaction.sh value1 value2

for more explanation why do this and caveats of makefile hackery read my answer to another very similar but seemingly not duplicate question: Passing arguments to "make run"

查看更多
够拽才男人
5楼-- · 2020-01-26 13:34

Much easier aproach. Consider a task:

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

Now when I want to call it I just run something like:

AT="build assets" make provision

or just:

make provision in this case AT is an empty string

查看更多
登录 后发表回答