Ich benutze Makefiles.
Ich habe ein Ziel namens, run
das das Build-Ziel ausführt. Vereinfacht sieht es wie folgt aus:
prog: ....
...
run: prog
./prog
Gibt es eine Möglichkeit, Argumente zu übergeben? Damit
make run asdf --> ./prog asdf
make run the dog kicked the cat --> ./prog the dog kicked the cat
Vielen Dank!
Antworten:
Ich weiß nicht, wie ich genau das tun kann, was Sie wollen, aber eine Problemumgehung könnte sein:
Dann:
quelle
$(foo)' or
$ {foo} 'ist eine gültige Referenz auf die Variable "foo". " und fährt fort, Beispiele zu geben, in denen nur $ () verwendet wird. Ah, gut.Diese Frage ist fast drei Jahre alt, aber trotzdem ...
Wenn Sie GNU make verwenden, ist dies einfach. Das einzige Problem besteht darin, dass
make
Argumente ohne Option in der Befehlszeile als Ziele interpretiert werden. Die Lösung besteht darin, sie in Nichtstun-Ziele zu verwandeln, alsomake
beschweren Sie sich nicht:Wenn Sie dies ausführen, erhalten Sie:
quelle
prog foo bar --baz
make
nicht--baz
als Befehlszeilenoption zu interpretieren :make -- prog foo bar --baz
. Das--
bedeutet "alles danach ist ein Argument, keine Option".RUN_ARGS
Verwendung definieren ?else
Zweig zum hinzufügenifeq
undRUN_ARGS
dort setzen?$(eval $(RUN_ARGS):dummy;@:)
, ohne dass ein Dummy-Ziel definiert ist.Für Standard-Make können Sie Argumente übergeben, indem Sie solche Makros definieren
dann benutze sie so
Referenzen für Make Microsofts NMake
quelle
Sie können die Variable wie folgt an das Makefile übergeben:
Verwendungszweck:
oder:
Alternativ können Sie die von Beta bereitgestellte Lösung verwenden :
Verwendungszweck:
quelle
TL; DR versuchen Sie nicht, dies zu tun
Erstellen Sie stattdessen ein Skript:
und mach das:
Antwort auf die gestellte Frage:
Sie können eine Variable im Rezept verwenden
Übergeben Sie dann eine Variablenzuweisung als Argument
Dies wird ausgeführt
./prog arg
.aber hüte dich vor Fallstricken. Ich werde auf die Fallstricke dieser Methode und anderer Methoden weiter unten eingehen.
Antwort auf die vermutete Absicht hinter der Frage:
Die Annahme: Sie möchten
prog
mit einigen Argumenten ausgeführt werden, müssen diese jedoch vor der Ausführung neu erstellen, falls erforderlich.Die Antwort: Erstellen Sie ein Skript, das bei Bedarf neu erstellt wird, und führen Sie dann prog mit args aus
Dieses Skript macht die Absicht sehr klar. Es verwendet make, um das zu tun, wofür es gut ist: Bauen. Es verwendet ein Shell-Skript, um das zu tun, wofür es gut ist: Stapelverarbeitung.
Außerdem können Sie mit der vollen Flexibilität und Ausdruckskraft eines Shell-Skripts alles tun, was Sie sonst noch benötigen, ohne die Einschränkungen eines Makefiles.
auch die aufrufende Syntax ist jetzt praktisch identisch:
vergleichen mit:
im Gegensatz zu
Hintergrund:
make ist nicht dafür ausgelegt, Argumente an ein Ziel zu übergeben. Alle Argumente in der Befehlszeile werden entweder als Ziel (auch als Ziel bezeichnet), als Option oder als Variablenzuweisung interpretiert.
Also, wenn Sie dies ausführen:
make wird interpretiert
run
undfoo
als Ziele (Targets) nach ihren Rezepten aktualisiert.--wat
als Option für machen. undvar=arg
als variable Zuordnung.Weitere Informationen finden Sie unter: https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals
Die Terminologie finden Sie unter: https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction
über die variable Zuweisungsmethode und warum ich dagegen empfehle
und die Variable im Rezept
Dies ist die "korrekteste" und einfachste Möglichkeit, Argumente an ein Rezept zu übergeben. Obwohl es verwendet werden kann, um ein Programm mit Argumenten auszuführen, ist es sicherlich nicht dafür ausgelegt, auf diese Weise verwendet zu werden. Siehe https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
Meiner Meinung nach hat dies einen großen Nachteil: Was Sie tun möchten, ist
prog
mit Argumenten zu laufenarg
. aber anstatt zu schreiben:du schreibst:
Dies wird noch umständlicher, wenn Sie versuchen, mehrere Argumente oder Argumente mit Leerzeichen zu übergeben:
vergleichen mit:
Für die Aufzeichnung
prog
sieht es so aus:Beachten Sie auch, dass Sie
$(var)
im Makefile keine Anführungszeichen setzen sollten :denn dann
prog
bekommt man immer nur ein argument:All dies ist, warum ich gegen diese Route empfehle.
Der Vollständigkeit halber sind hier einige andere Methoden aufgeführt, um "Argumente zu übergeben, um sie auszuführen".
Methode 1:
super kurze Erklärung: aktuelles Ziel aus der Liste der Ziele herausfiltern. Erstelle catch all target (
%
), was nichts dazu beiträgt, die anderen Ziele stillschweigend zu ignorieren.Methode 2:
super kurze Erklärung: Wenn das Ziel ist,
run
entfernen Sie das erste Ziel und erstellen Sie keine Ziele für die verbleibenden Ziele miteval
.Mit beiden können Sie so etwas schreiben
Weitere Informationen finden Sie im Handbuch von make: https://www.gnu.org/software/make/manual/html_node/index.html
Probleme der Methode 1:
Argumente, die mit einem Bindestrich beginnen, werden von make interpretiert und nicht als Ziel übergeben.
Problemumgehung
Argumente mit Gleichheitszeichen werden von make interpretiert und nicht übergeben
Keine Problemumgehung
Argumente mit Leerzeichen sind umständlich
Keine Problemumgehung
Wenn ein Argument zufällig
run
(gleich dem Ziel) ist, wird es ebenfalls entferntläuft
./prog foo bar
statt./prog foo bar run
Problemumgehung mit Methode 2 möglich
Wenn ein Argument ein legitimes Ziel ist, wird es ebenfalls ausgeführt.
läuft
./prog foo bar clean
aber auch das Rezept für das Zielclean
(vorausgesetzt es existiert).Problemumgehung mit Methode 2 möglich
Wenn Sie ein legitimes Ziel falsch eingeben, wird es aufgrund des Ziels "Alle fangen" stillschweigend ignoriert.
wird einfach still ignorieren
celan
.Problemumgehung ist, alles wortreich zu machen. Sie sehen also, was passiert. aber das erzeugt viel Rauschen für die legitime Ausgabe.
Probleme der Methode 2:
Wenn ein Argument denselben Namen wie ein vorhandenes Ziel hat, gibt make eine Warnung aus, dass es überschrieben wird.
Keine Problemumgehung, die ich kenne
Argumente mit einem Gleichheitszeichen werden weiterhin von make interpretiert und nicht übergeben
Keine Problemumgehung
Argumente mit Leerzeichen sind immer noch umständlich
Keine Problemumgehung
Argumente mit Leerzeichen, die
eval
versuchen zu erstellen, bewirken nichts.Problemumgehung: Erstellen Sie das globale Ziel "catch all", ohne die oben genannten Schritte auszuführen. mit dem Problem wie oben, dass es wieder stillschweigend falsch eingegebene legitime Ziele ignoriert.
Es wird verwendet
eval
, um das Makefile zur Laufzeit zu ändern. Wie viel schlimmer können Sie in Bezug auf Lesbarkeit und Debugbarkeit und das Prinzip des geringsten Erstaunens gehen .Problemumgehung: Tun Sie dies nicht !! 1 Schreiben Sie stattdessen ein Shell-Skript, das make ausführt und dann ausgeführt wird
prog
.Ich habe nur mit Gnu Make getestet. andere Marken haben möglicherweise ein anderes Verhalten.
TL; DR versuchen Sie nicht, dies zu tun
Erstellen Sie stattdessen ein Skript:
und mach das:
quelle
Hier ist eine andere Lösung, die bei einigen dieser Anwendungsfälle helfen könnte:
Mit anderen Worten, wählen Sie ein Präfix (
test-
in diesem Fall) und übergeben Sie den Zielnamen direkt an das Programm / den Runner. Ich denke, dies ist meistens nützlich, wenn es sich um ein Runner-Skript handelt, das den Zielnamen in etwas Nützliches für das zugrunde liegende Programm auspacken kann.quelle
$*
nur den Teil des Ziels übergeben, der dem entspricht%
.Schauen Sie sich die Syntax von der Manpage für GNU make an
Sie können mehrere Ziele angeben, daher 'nein' (zumindest nein genau so, wie Sie es angegeben haben).
quelle
Sie können jedes n-te Argument in der Befehlszeile explizit extrahieren. Zu diesem Zweck können Sie die Variable MAKECMDGOALS verwenden. Sie enthält die Liste der Befehlszeilenargumente für 'make', die als Liste der Ziele interpretiert werden. Wenn Sie das n-te Argument extrahieren möchten, können Sie diese Variable in Kombination mit der Funktion "Wort" verwenden. Wenn Sie beispielsweise das zweite Argument möchten, können Sie es wie folgt in einer Variablen speichern:
quelle
make: *** No rule to make target 'arg'. Stop.
anon ,
run: ./prog
sieht ein bisschen seltsam aus, da der rechte Teil ein Ziel sein sollte, alsorun: prog
besser aussieht.Ich würde einfach vorschlagen:
und ich möchte hinzufügen, dass Argumente übergeben werden können:
make arg1="asdf" run
arg1="asdf" make run
quelle
Hier ist mein Beispiel. Beachten Sie, dass ich unter Windows 7 mit mingw32-make.exe schreibe, das mit Dev-Cpp geliefert wird. (Ich habe c: \ Windows \ System32 \ make.bat, daher heißt der Befehl immer noch "make".)
Verwendung zur regelmäßigen Reinigung:
Verwendung zum Bereinigen und Erstellen eines Backups in mydir /:
quelle
Nicht allzu stolz darauf, aber ich wollte keine Umgebungsvariablen übergeben, also habe ich die Art und Weise, wie ein vordefinierter Befehl ausgeführt wird, umgekehrt:
Dadurch wird der Befehl gedruckt, den Sie ausführen möchten. Bewerten Sie ihn also einfach in einer Unterschale:
quelle
Ich habe einen Weg gefunden, die Argumente mit einem Gleichheitszeichen (=) zu erhalten! Die Antwort ist insbesondere eine Ergänzung zu @lesmanas Antwort (da sie die vollständigste und erklärteste hier ist), aber sie wäre zu groß, um sie als Kommentar zu schreiben. Ich wiederhole noch einmal seine Nachricht: TL; DR versuche das nicht!
Ich brauchte einen Weg, um mein Argument zu behandeln
--xyz-enabled=false
(da der Standardwert wahr ist), von dem wir alle inzwischen wissen, dass dies kein Make-Ziel ist und daher nicht Teil davon$(MAKECMDGOALS)
.Beim Betrachten aller Variablen von make durch Echo des habe
$(.VARIABLES)
ich diese interessanten Ausgaben erhalten:Dies ermöglicht es uns, zwei Wege zu gehen: entweder alles mit einer
--
(falls dies für Ihren Fall zutrifft) zu beginnen oder in die GNU make-spezifische (wahrscheinlich nicht für uns vorgesehene) Variable zu schauen-*-command-variables-*-
. ** Weitere Optionen finden Sie in der Fußzeile. ** In meinem Fall enthielt diese Variable:Mit dieser Variablen können wir sie mit der bereits vorhandenen Lösung kombinieren
$(MAKECMDGOALS)
und damit definieren:und Verwenden mit (explizite Verwechslung der Reihenfolge der Argumente):
ist zurückgekommen:
Wie Sie sehen können, verlieren wir die Gesamtreihenfolge der Argumente. Der Teil mit den "Zuweisungs" -Args scheint umgekehrt worden zu sein, die Reihenfolge der "Ziel" -Args wird beibehalten. Ich habe die "Zuweisungs" -Args am Anfang platziert, hoffentlich ist es Ihrem Programm egal, wo das Argument platziert ist.
Update: Die folgenden Variablen sehen ebenfalls vielversprechend aus:
quelle
Ein weiterer Trick, den ich benutze, ist die
-n
Flagge, diemake
einen Trockenlauf vorschreibt. Zum Beispiel,quelle