Come passare l'argomento al Makefile dalla riga di comando?


109

Come passare l'argomento al Makefile dalla riga di comando?

Capisco che posso fare

$ make action VAR="value"
$ value

con Makefile

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

Come ottengo il seguente comportamento?

$ make action value
value

?

Che ne dite di

$make action value1 value2
value1 value2


3
Possibile duplicato di Passing arguments per "make run"
lesmana

Risposte:


212

Probabilmente non dovresti farlo; stai rompendo lo schema di base di come funziona Make. Ma eccolo qui:

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

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

EDIT:
per spiegare il primo comando,

$(MAKECMDGOALS) è l'elenco di "obiettivi" enunciati sulla riga di comando, ad esempio "azione valore1 valore2".

$@è una variabile automatica per il nome del target della regola, in questo caso "azione".

filter-outè una funzione che rimuove alcuni elementi da un elenco. Quindi $(filter-out bar, foo bar baz)ritorna foo baz(può essere più sottile, ma non abbiamo bisogno di sottigliezza qui).

Mettili insieme e $(filter-out $@,$(MAKECMDGOALS))restituisce l'elenco dei target specificati sulla riga di comando diversi da "action", che potrebbe essere "value1 value2".


1
$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')omettere tutti gli obiettivi prima e considerare i seguenti come argomenti:make target1 target2 action value1 value2
Evgeniy Generalov

1
Perdonate la mia ignoranza. Ho provato a cercare su Google %:e @:non riesco a trovare informazioni su cosa fanno quelle "direttive" (o come si chiamano). Potresti spiegare per favore?
Jon

15
@ Jon: il manuale è qui . La parte composta da %:ed @:è una regola . Il nome di destinazione %significa che è una regola che corrisponde a qualsiasi cosa ; cioè, se Make non riesce a trovare un altro modo per costruire la cosa che gli dici di costruire, eseguirà quella regola. La @:è una ricetta ; i :mezzi non fanno nulla, ei @mezzi lo fanno silenziosamente.
Beta

Grazie. Avevo letto quel manuale e all'inizio non avevo considerato che %:fosse effettivamente % :un nome di destinazione di tipo jolly. Non vedo nulla in quella pagina di manuale riguardo @:però ... suggerisce che una regola "non fare nulla" avrebbe semplicemente un ;dopo la specifica di destinazione, quindi, non sarebbe più accurato scrivere % : ;come il "carattere jolly -Niente "regola?
Jon

1
filter-outnon funziona quando l'azione è una dipendenza della destinazione specificata sulla riga di comando, perché $@verrà impostata sul nome della dipendenza, non sull'argomento originale chiamato sulla riga di comando. Invece, assegno MAKECMDGOALSa un array di shell e quindi rimuovo il primo elemento:@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")
Gingi

18

Ecco una soluzione funzionante generica basata su @ Beta

Sto usando GNU Make 4.1 con SHELL=/bin/bashsopra il mio Makefile, quindi YMMV!

Questo ci permette di accettare argomenti extra (non facendo nulla quando otteniamo un lavoro che non corrisponde, piuttosto che lanciare un errore).

%:
    @:

E questa è una macro che ci fornisce gli argomenti:

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

Ecco un lavoro che potrebbe chiamare questo:

test:
    @echo $(call args,defaultstring)

Il risultato sarebbe:

$ make test
defaultstring
$ make test hi
hi

Nota! Potrebbe essere meglio usare un "Taskfile", che è un pattern bash che funziona in modo simile a make, solo senza le sfumature di Maketools. Vedi https://github.com/adriancooney/Taskfile


Ha funzionato!! Ad altre persone che lo provano, assicurati che ci sia tabprima @echo, no space.
Abdullah Al Maruf - Tuhin

11

Approccio molto più semplice. Considera un compito:

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

Ora, quando voglio chiamarlo, eseguo qualcosa del tipo:

AT="build assets" make provision

o semplicemente:

make provisionin questo caso ATè una stringa vuota


-2

non provare a farlo

$ make action value1 value2

invece crea script:

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

e fai questo:

$ ./buildthenaction.sh value1 value2

per ulteriori spiegazioni sul perché fare questo e avvertimenti sull'hackeraggio del makefile leggi la mia risposta a un'altra domanda molto simile ma apparentemente non duplicata: Passaggio di argomenti a "make run"

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.