Como passar o argumento para o Makefile da linha de comando?

109

Como passar o argumento para o Makefile da linha de comando?

Eu entendo que posso fazer

$ make action VAR="value"
$ value

com Makefile

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

Como obtenho o seguinte comportamento?

$ make action value
value

?

E se

$make action value1 value2
value1 value2
Meng Lu
fonte
3
Possível duplicata de Passing arguments to "make run"
lesmana

Respostas:

212

Você provavelmente não deveria fazer isso; você está quebrando o padrão básico de como o Make funciona. Mas aqui está:

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

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

EDIT:
Para explicar o primeiro comando,

$(MAKECMDGOALS) é a lista de "alvos" explicitada na linha de comando, por exemplo, "ação valor1 valor2".

$@é uma variável automática para o nome do destino da regra, neste caso "ação".

filter-outé uma função que remove alguns elementos de uma lista. Então $(filter-out bar, foo bar baz)retorna foo baz(pode ser mais sutil, mas não precisamos de sutileza aqui).

Reúna-os e $(filter-out $@,$(MAKECMDGOALS))retorna a lista de destinos especificados na linha de comando diferente de "ação", que pode ser "valor1 valor2".

Beta
fonte
1
$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')omitir todos os alvos antes e apenas considerar o seguinte como argumentos:make target1 target2 action value1 value2
Evgeniy Generalov
1
Perdoe minha ignorância. Eu tentei pesquisar no Google %:e @:não consigo encontrar informações sobre o que essas "diretivas" (ou o que quer que sejam chamadas) fazem. Você poderia explicar?
Jon
15
@Jon: O manual está aqui . A parte que consiste em %:e @:é uma regra . O nome do alvo %significa que é uma regra que corresponde a tudo ; ou seja, se o Make não conseguir encontrar nenhuma outra maneira de construir o que você disse para construir, ele executará essa regra. O @:é uma receita ; os :meios não fazem nada e os @meios o fazem silenciosamente.
Beta
Obrigado. Eu estava lendo aquele manual e não considerei a princípio, %:na verdade % :, um nome de destino do tipo curinga. Não vejo nada nessa página de manual a respeito @:... sugere que uma regra "não fazer nada" simplesmente teria um ;após a especificação de destino, então, não seria mais preciso escrever % : ;como o "curinga faça -nada "regra?
Jon
1
filter-outnão funciona quando a ação é uma dependência do destino especificado na linha de comando, porque $@será definido como o nome da dependência, não o argumento original chamado na linha de comando. Em vez disso, atribuo MAKECMDGOALSa uma matriz de shell e removo o primeiro elemento:@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")
Gingi
18

Aqui está uma solução de trabalho genérica baseada em @ Beta's

Estou usando o GNU Make 4.1 com SHELL=/bin/bashno topo do meu Makefile, então YMMV!

Isso nos permite aceitar argumentos extras (sem fazer nada quando obtemos um trabalho que não corresponde, em vez de gerar um erro).

%:
    @:

E esta é uma macro que obtém os argumentos para nós:

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

Aqui está um trabalho que pode chamar este:

test:
    @echo $(call args,defaultstring)

O resultado seria:

$ make test
defaultstring
$ make test hi
hi

Nota! Talvez seja melhor usar um "Arquivo de tarefas", que é um padrão bash que funciona de forma semelhante ao make, mas sem as nuances do Maketools. Veja https://github.com/adriancooney/Taskfile

M3D
fonte
Funcionou!! PARA outras pessoas tentando, certifique-se de que há tabantes @echo, não space.
Abdullah Al Maruf - Tuhin
11

Abordagem muito mais fácil. Considere uma tarefa:

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

Agora, quando quero chamá-lo, apenas executo algo como:

AT="build assets" make provision

ou apenas:

make provisionneste caso ATé uma string vazia

Kharandziuk
fonte
-2

não tente fazer isso

$ make action value1 value2

em vez disso, crie o script:

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

e faça isso:

$ ./buildthenaction.sh value1 value2

para obter mais explicações sobre por que fazer isso e advertências sobre hackeamento de makefile, leia minha resposta a outra pergunta muito semelhante, mas aparentemente não duplicada: Passando argumentos para "make run"

Lesmana
fonte