Wie übergebe ich ein Argument von der Kommandozeile an Makefile?


109

Wie übergebe ich ein Argument von der Kommandozeile an Makefile?

Ich verstehe, dass ich es tun kann

$ make action VAR="value"
$ value

mit Makefile

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

Wie erhalte ich das folgende Verhalten?

$ make action value
value

?

Wie wäre es mit

$make action value1 value2
value1 value2

2
Ähnlich:
Übergabe von

3
Mögliches Duplikat der
Übergabe

Antworten:


211

Sie sollten dies wahrscheinlich nicht tun. Sie brechen das Grundmuster, wie Make funktioniert. Aber hier ist es:

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

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

EDIT:
Um den ersten Befehl zu erklären,

$(MAKECMDGOALS) ist die Liste der "Ziele", die in der Befehlszeile angegeben sind, z. B. "Aktionswert1 Wert2".

$@ist eine automatische Variable für den Namen des Ziels der Regel, in diesem Fall "Aktion".

filter-outist eine Funktion, die einige Elemente aus einer Liste entfernt. Also $(filter-out bar, foo bar baz)kehrt zurück foo baz(es kann subtiler sein, aber wir brauchen hier keine Subtilität).

Fügen Sie diese zusammen und geben Sie $(filter-out $@,$(MAKECMDGOALS))die Liste der Ziele zurück, die in der Befehlszeile angegeben sind, außer "Aktion", möglicherweise "Wert1 Wert2".


1
$(shell echo $(MAKECMDGOALS) | sed 's!^.* $@ !!')um alle Ziele vorher wegzulassen und nur Folgendes als Argumente zu betrachten:make target1 target2 action value1 value2
Evgeniy Generalov

1
Verzeihen Sie meine Unwissenheit. Ich habe versucht zu googeln %:und @:kann keine Informationen darüber finden, was diese "Anweisungen" (oder wie auch immer sie genannt werden) tun. Könnten Sie bitte erklären?
Jon

15
@ Jon: Das Handbuch ist hier . Der Teil bestehend aus %:und@: ist eine Regel . Der Zielname %bedeutet, dass es sich um eine Regel handelt, die mit allem übereinstimmt . Das heißt, wenn Make keine andere Möglichkeit findet, das Objekt zu erstellen, das Sie erstellen sollen, wird diese Regel ausgeführt. Das @:ist ein Rezept ; Die :Mittel tun nichts und die @Mittel tun es still.
Beta

Vielen Dank. Ich hatte dieses Handbuch gelesen und zuerst nicht darüber nachgedacht, dass %:es sich tatsächlich um % :einen Zielnamen vom Typ Wildcard handelte. Ich sehe auf dieser Handbuchseite jedoch nichts in Bezug auf @:... es deutet darauf hin, dass eine "Nichtstun" -Regel einfach ein " ;Nach der Zielspezifikation" haben würde , also wäre es nicht genauer zu schreiben % : ;als die "Platzhalter" -nichts "Regel?
Jon

1
filter-outfunktioniert nicht, wenn die Aktion eine Abhängigkeit des in der Befehlszeile angegebenen Ziels ist, da $@der Name der Abhängigkeit festgelegt wird und nicht das ursprüngliche Argument, das in der Befehlszeile aufgerufen wird. Stattdessen MAKECMDGOALS@ args=($(MAKECMDGOALS)); args=("$${args[@]:1}")
weise

18

Hier ist eine generische Arbeitslösung, die auf @ Beta basiert

Ich benutze GNU Make 4.1 SHELL=/bin/bashauf meinem Makefile, also YMMV!

Dies ermöglicht es uns, zusätzliche Argumente zu akzeptieren (indem wir nichts tun, wenn wir einen Job erhalten, der nicht übereinstimmt, anstatt einen Fehler auszulösen).

%:
    @:

Und dies ist ein Makro, das die Argumente für uns erhält:

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

Hier ist ein Job, der diesen nennen könnte:

test:
    @echo $(call args,defaultstring)

Das Ergebnis wäre:

$ make test
defaultstring
$ make test hi
hi

Hinweis! Sie sind möglicherweise besser dran, wenn Sie ein "Taskfile" verwenden, ein Bash-Muster, das ähnlich funktioniert, nur ohne die Nuancen von Maketools. Siehe https://github.com/adriancooney/Taskfile


Es funktionierte!! Stellen Sie für andere Leute, die es ausprobieren, sicher, dass es tabvorher @echokeine gibt space.
Abdullah Al Maruf - Tuhin

11

Viel einfacher Ansatz. Betrachten Sie eine Aufgabe:

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

Wenn ich es jetzt nennen möchte, führe ich einfach so etwas aus wie:

AT="build assets" make provision

oder nur:

make provisionIn diesem Fall AThandelt es sich um eine leere Zeichenfolge


-2

versuche das nicht zu tun

$ make action value1 value2

Erstellen Sie stattdessen ein Skript:

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

und mach das:

$ ./buildthenaction.sh value1 value2

Für weitere Erklärungen, warum dies und Vorbehalte gegen Makefile-Hackery tun, lesen Sie meine Antwort auf eine andere sehr ähnliche, aber scheinbar nicht doppelte Frage: Übergeben von Argumenten an "make run"

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.