In einem Makefile muss für ein deploy
Rezept eine Umgebungsvariable ENV
festgelegt werden, damit sie sich selbst ordnungsgemäß ausführt, während es anderen egal ist, z.
ENV =
.PHONY: deploy hello
deploy:
rsync . $(ENV).example.com:/var/www/myapp/
hello:
echo "I don't care about ENV, just saying hello!"
Wie kann ich sicherstellen, dass diese Variable festgelegt ist, z. B.: Gibt es eine Möglichkeit, diese Makefile-Variable als Voraussetzung für das Bereitstellungsrezept zu deklarieren, z.
deploy: make-sure-ENV-variable-is-set
?
Danke dir.
make
es festgelegt oder eine Warnung ausgegeben oder ein schwerwiegender Fehler generiert werden?make ENV=dev
aber wenn er es vergisstENV=dev
,deploy
Antworten:
Dies führt zu einem schwerwiegenden Fehler, wenn er nicht
ENV
definiert ist und von etwas benötigt wird (jedenfalls in GNUMake).(Beachten Sie, dass ifndef und endif nicht eingerückt sind - sie steuern, was make "sieht" und werden wirksam, bevor das Makefile ausgeführt wird. "$ (Fehler" wird mit einer Registerkarte eingerückt, sodass es nur im Kontext der Regel ausgeführt wird.)
quelle
ENV is undefined
beim Ausführen einer Aufgabe, für die Check-Env nicht erforderlich ist.check-env
Regel. Make wird es erst erweitern, wenn / bis die Regel ausgeführt wird. Wenn es nicht mit einem TAB beginnt (wie im Beispiel von @ rane), interpretiert Make es als nicht in einer Regel enthalten und wertet es aus, bevor eine Regel ausgeführt wird, unabhängig vom Ziel.Sie können ein implizites Schutzziel erstellen, das überprüft, ob die Variable im Stamm wie folgt definiert ist:
Anschließend fügen Sie ein
guard-ENVVAR
Ziel an einer beliebigen Stelle hinzu, an der Sie behaupten möchten, dass eine Variable wie folgt definiert ist:Wenn Sie aufrufen
make change-hostname
, ohneHOSTNAME=somehostname
den Aufruf hinzuzufügen , wird eine Fehlermeldung angezeigt, und der Build schlägt fehl.quelle
if [ -z '${${*}}' ]; then echo 'Environment variable $* not set' && exit 1; fi
: DInline-Variante
In meinen Makefiles verwende ich normalerweise einen Ausdruck wie:
Die Gründe:
Vergessen Sie nicht den Kommentar, der für das Debuggen wichtig ist:
... zwingt dich, das Makefile nachzuschlagen, während ...
... erklärt direkt, was los ist
Globale Variante (der Vollständigkeit halber, aber nicht gefragt)
Über Ihr Makefile können Sie auch schreiben:
Warnungen:
clean
anwenden : Auch das Ziel schlägt fehl, wenn ENV nicht eingestellt ist. Ansonsten siehe Hudons Antwort, die komplexer istquelle
@
. -> gnu.org/software/make/manual/make.html#Echoing@test -n "$(name)" || (echo 'A name must be defined for the backup. Ex: make backup name=xyz' && exit 1)
Ein mögliches Problem mit den gegebenen Antworten ist bisher, dass die Abhängigkeitsreihenfolge in make nicht definiert ist. Zum Beispiel:
Wenn
target
einige Abhängigkeiten vorliegen, kann nicht garantiert werden, dass diese in einer bestimmten Reihenfolge ausgeführt werden.Die Lösung hierfür (um sicherzustellen, dass ENV überprüft wird, bevor Rezepte ausgewählt werden) besteht darin, ENV während des ersten Durchgangs von make außerhalb eines Rezepts zu überprüfen:
Sie können sich über die verschiedenen Funktionen / Variablen informieren, die hier verwendet werden, und können
$()
nur explizit angeben, dass wir mit "nichts" vergleichen.quelle
Ich habe festgestellt, dass die beste Antwort nicht als Voraussetzung verwendet werden kann, außer für andere PHONY-Ziele. Wenn es als Abhängigkeit für ein Ziel verwendet wird, das eine tatsächliche Datei ist, erzwingt
check-env
die Verwendung , dass dieses Dateiziel neu erstellt wird.Andere Antworten sind global (z. B. ist die Variable für alle Ziele im Makefile erforderlich ) oder verwenden die Shell, z. B. wenn ENV fehlte, würde make unabhängig vom Ziel beendet.
Eine Lösung, die ich für beide Probleme gefunden habe, ist
Die Ausgabe sieht aus wie
value
hat einige beängstigende Vorbehalte, aber für diese einfache Verwendung glaube ich, dass es die beste Wahl ist.quelle
Wie ich sehe, benötigt der Befehl selbst die Variable ENV, damit Sie sie im Befehl selbst überprüfen können:
quelle
deploy
nicht unbedingt das einzige Rezept ist, das diese Variable benötigt. Mit dieser Lösung muss ich den StatusENV
für jeden einzelnen testen ... während ich ihn als eine einzige (Art) Voraussetzung behandeln möchte.Ich weiß, dass dies alt ist, aber ich dachte, ich würde meine eigenen Erfahrungen für zukünftige Besucher einbringen, da es meiner Meinung nach etwas ordentlicher ist.
Typischerweise
make
wird verwendensh
als Standardschale ( eingestellt über die spezielleSHELL
Variable ). Insh
und seinen Derivaten, ist es trivial , um mit einer Fehlermeldung beendet , wenn eine Umgebungsvariable abzurufen , wenn es nicht gesetzt ist oder null , indem Sie:${VAR?Variable VAR was not set or null}
.Wenn Sie dies erweitern, können Sie ein wiederverwendbares make-Ziel schreiben, mit dem andere Ziele fehlgeschlagen werden können, wenn keine Umgebungsvariable festgelegt wurde:
Bemerkenswerte Dinge:
$$
) ist erforderlich, um die Erweiterung auf die Shell anstatt auf die Shell zu verschiebenmake
test
dient nur dazu, zu verhindern, dass die Shell versucht, den Inhalt von auszuführenVAR
(es dient keinem anderen wichtigen Zweck)..check-env-vars
kann trivially zu überprüfen , um weitere Umgebungsvariablen erweitert werden, fügt die jeweils nur eine Zeile (z@test $${NEWENV?Please set environment variable NEWENV}
)quelle
ENV
Leerzeichen enthält Dies scheint (zumindest für mich) nichtSie können
ifdef
anstelle eines anderen Ziels verwenden.quelle
deploy
ist es nicht das einzige Rezept, das dieENV
Statusvariable überprüfen muss ..PHONY: deploy
unddeploy:
vor dem ifdef-Block und entfernen Sie die Duplizierung. (Übrigens habe ich die Antwort bearbeitet, um die richtige Methode wiederzugeben)