Jak przekazać argument do Makefile z linii poleceń?

109

Jak przekazać argument do Makefile z linii poleceń?

Rozumiem, że mogę to zrobić

$ make action VAR="value"
$ value

z Makefile

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

Jak uzyskać następujące zachowanie?

$ make action value
value

?

Co powiesz na

$make action value1 value2
value1 value2
Meng Lu
źródło

Odpowiedzi:

212

Prawdopodobnie nie powinieneś tego robić; łamiesz podstawowy schemat działania aplikacji Make. Ale oto jest:

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

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

EDYCJA:
Aby wyjaśnić pierwsze polecenie,

$(MAKECMDGOALS) to lista „celów” wypisana w wierszu poleceń, np. „wartość akcji1 wartość2”.

$@to automatyczna zmienna dla nazwy celu reguły, w tym przypadku „akcja”.

filter-outto funkcja, która usuwa niektóre elementy z listy. Więc $(filter-out bar, foo bar baz)zwraca foo baz(może być bardziej subtelny, ale nie potrzebujemy tutaj subtelności).

Połącz je razem i $(filter-out $@,$(MAKECMDGOALS))zwróci listę celów określonych w wierszu poleceń innych niż „akcja”, która może mieć postać „wartość1 wartość2”.

Beta
źródło
1
$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')pominąć wszystkie wcześniejsze cele i po prostu rozważyć następujące argumenty:make target1 target2 action value1 value2
Evgeniy Generalov
1
Przepraszam za moją ignorancję. Próbowałem googlować %:i @:nie mogę znaleźć informacji o tym, co robią te „dyrektywy” (czy jakkolwiek się nazywają). Czy mógłbyś wyjaśnić?
Jon
15
@Jon: Podręcznik jest tutaj . Część składająca się z reguły%: i @:jest regułą . Nazwa celu %oznacza, że ​​jest to reguła, która pasuje do wszystkiego ; to znaczy, jeśli Make nie może znaleźć innego sposobu na zbudowanie rzeczy, którą każesz mu zbudować, wykona tę regułę. To @:jest przepis ; te :środki nie robić nic, a @oznacza to zrobić dyskretnie.
Beta
Dzięki. Czytałem ten podręcznik i na początku nie brałem pod uwagę, że %:była % :to nazwa docelowa typu wieloznacznego. Nie widzę nic na tej stronie podręcznika co do @:tego… sugeruje to, że reguła „nic nie rób” miałaby po prostu znak ;po specyfikacji celu, więc czy nie byłoby dokładniej pisać % : ;tak, jak robi to „symbol wieloznaczny” - nic nie jest regułą?
Jon
1
filter-outnie działa, gdy akcja jest zależnością celu określonego w wierszu poleceń, ponieważ $@zostanie ustawiona na nazwę zależności, a nie oryginalny argument wywoływany w wierszu poleceń. Zamiast tego przypisuję MAKECMDGOALSdo tablicy powłoki, a następnie usuwam pierwszy element:@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")
Gingi
18

Oto ogólne działające rozwiązanie oparte na @ Beta

Używam GNU Make 4.1 SHELL=/bin/bashna szczycie mojego pliku Makefile, więc YMMV!

To pozwala nam akceptować dodatkowe argumenty (nie robiąc nic, gdy otrzymujemy zadanie, które nie pasuje, zamiast zgłaszać błąd).

%:
    @:

A to jest makro, które pobiera argumenty za nas:

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

Oto praca, która może nazwać tę:

test:
    @echo $(call args,defaultstring)

Wynik byłby taki:

$ make test
defaultstring
$ make test hi
hi

Uwaga! Lepiej by było, gdybyś użył „Taskfile”, który jest wzorcem basha, który działa podobnie do make, tylko bez niuansów Maketools. Zobacz https://github.com/adriancooney/Taskfile

M3D
źródło
Zadziałało!! DO innych osób, które go wypróbowują, upewnij się, że było tabwcześniej @echo, a nie space.
Abdullah Al Maruf - Tuhin
11

O wiele łatwiejsze podejście. Rozważ zadanie:

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

Teraz, kiedy chcę to nazwać, po prostu uruchamiam coś takiego:

AT="build assets" make provision

Lub tylko:

make provisionw tym przypadku ATjest to pusty ciąg

kharandziuk
źródło
-2

nie próbuj tego robić

$ make action value1 value2

zamiast tego utwórz skrypt:

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

i zrób to:

$ ./buildthenaction.sh value1 value2

aby uzyskać więcej wyjaśnień, dlaczego to robię i zastrzeżenia dotyczące hakowania plików makefile, przeczytaj moją odpowiedź na inne bardzo podobne, ale pozornie nie zduplikowane pytanie: Przekazywanie argumentów do polecenia „make run”

lesmana
źródło