Ja, Sie können das Schlüsselwort define verwenden, um eine mehrzeilige Variable wie folgt zu deklarieren:
define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.
It can be downloaded from $(DOWNLOAD_URL).
etc, etc.
endef
Der schwierige Teil besteht darin, Ihre mehrzeilige Variable wieder aus dem Makefile zu entfernen. Wenn Sie nur "echo $ (ANNOUNCE_BODY)" verwenden, sehen Sie das Ergebnis, das andere hier gepostet haben - die Shell versucht, die zweite und die nachfolgenden Zeilen der Variablen selbst als Befehle zu behandeln.
Sie können den Variablenwert jedoch unverändert als Umgebungsvariable in die Shell exportieren und ihn dann als Umgebungsvariable (NICHT als make-Variable) aus der Shell referenzieren. Beispielsweise:
export ANNOUNCE_BODY
all:
@echo "$$ANNOUNCE_BODY"
Beachten Sie die Verwendung von $$ANNOUNCE_BODY
und geben Sie eine Shell-Umgebungsvariablenreferenz an, anstatt $(ANNOUNCE_BODY)
eine reguläre Make-Variablenreferenz. Stellen Sie außerdem sicher, dass Sie Anführungszeichen um Ihre Variablenreferenz verwenden, um sicherzustellen, dass die Zeilenumbrüche nicht von der Shell selbst interpretiert werden.
Natürlich kann dieser spezielle Trick plattform- und Shell-empfindlich sein. Ich habe es unter Ubuntu Linux mit GNU Bash 3.2.13 getestet. YMMV.
export ANNOUNCE_BODY
Setzt nur die Variable innerhalb von Regeln - es erlaubt nicht, auf $$ ANNOUNCE_BODY zu verweisen, um andere Variablen zu definieren.ANNOUNCE_BODY
in anderen Variablendefinitionen verwenden möchten , verweisen Sie einfach wie bei jeder anderen make-Variablen darauf. Zum BeispielOTHER=The variable ANNOUNCE_BODY is $(ANNOUNCE_BODY)
. Natürlich brauchen Sie denexport
Trick noch, wenn SieOTHER
einen Befehl ausführen möchten .Ein anderer Ansatz, um Ihre mehrzeilige Variable wieder aus dem Makefile zu entfernen (von Eric Melski als "der knifflige Teil" bezeichnet), besteht darin, die
subst
Funktion zu verwenden, um diedefine
in Ihrer mehrzeiligen Zeichenfolge eingeführten Zeilenumbrüche durch zu ersetzen\n
. Verwenden Sie dann -e mitecho
, um sie zu interpretieren. Möglicherweise müssen Sie .SHELL = bash setzen, um ein Echo zu erhalten, das dies tut.Ein Vorteil dieses Ansatzes besteht darin, dass Sie auch andere Escapezeichen in Ihren Text einfügen und diese respektieren lassen.
Diese Art der Synthese aller bisher genannten Ansätze ...
Sie landen mit:
Beachten Sie, dass die einfachen Anführungszeichen im letzten Echo von entscheidender Bedeutung sind.
quelle
=
After entfernendefine ANNOUNCE_BODY
, um es zum Laufen zu bringen.Angenommen, Sie möchten den Inhalt Ihrer Variablen nur in der Standardausgabe drucken, gibt es eine andere Lösung:
quelle
make: 'do-echo' is up to date.
. Mit einem "no op" -Kommand konnte ich es zum Schweigen bringen:@: $(info $(YOUR_MULTILINE_VAR))
.PHONY
Ihrem Makefile mitteilen, dass für diese Regel nichts zu überprüfen ist. Makefiles waren ursprünglich für Compiler gedacht, wenn ich mich nicht irre, alsomake
mache ich etwas Magie, die ich nicht verstehe, um vorauszusehen, dass die Regel nichts ändert, und als solche davon ausgeht, dass sie "erledigt" ist. Wenn Sie.PHONY do-echo
Ihre Datei hinzufügenmake
, wird dies angewiesen, dies zu ignorieren und den Code trotzdem auszuführen.$(info ...)
außerhalb einer Make-Regel platzieren. Es wird weiterhin eine Ausgabe generiert.Ja. Sie entkommen den Zeilenumbrüchen mit
\
:aktualisieren
Ah, du willst die Zeilenumbrüche? Dann nein, ich glaube nicht, dass es in Vanille Make einen Weg gibt. Sie können jedoch immer ein Here-Dokument im Befehlsteil verwenden
[Dies funktioniert nicht, siehe Kommentar von MadScientist]
quelle
Nur ein Nachtrag zu Eric Melskis Antwort: Sie können die Ausgabe von Befehlen in den Text aufnehmen, müssen jedoch die Makefile-Syntax "$ (shell foo)" anstelle der Shell-Syntax "$ (foo)" verwenden. Beispielsweise:
quelle
Dies gibt hier kein Dokument an, zeigt jedoch eine mehrzeilige Nachricht auf eine Weise an, die für Pipes geeignet ist.
=====
=====
Sie können auch Gnus aufrufbare Makros verwenden:
=====
=====
Hier ist die Ausgabe:
=====
=====
quelle
Warum verwenden Sie nicht das Zeichen \ n in Ihrer Zeichenfolge, um das Zeilenende zu definieren? Fügen Sie außerdem den zusätzlichen Backslash hinzu, um ihn über mehrere Zeilen hinzuzufügen.
quelle
$(subst \n ,\n,$(TEXT))
obwohl ich mir wünschte, es gäbe einen besseren Weg!GNU `make 'Handbuch, 6.8: Definieren mehrzeiliger Variablen
quelle
echo
.Sie sollten "define / endef" verwenden. Konstrukt erstellen:
Dann sollten Sie den Wert dieser Variablen an den Shell-Befehl übergeben. Wenn Sie dies jedoch mit "Variable ersetzen" ausführen, wird der Befehl in mehrere Teile aufgeteilt:
Qouting hilft auch nicht.
Der beste Weg, einen Wert zu übergeben, besteht darin, ihn über die Umgebungsvariable zu übergeben:
Beachten:
quelle
Im Geiste von .ONESHELL ist es möglich, in .ONESHELL-herausfordernden Umgebungen ziemlich nahe zu kommen:
Ein Anwendungsbeispiel wäre etwa so:
Das zeigt die Ausgabe (unter der Annahme von PID 27801):
Dieser Ansatz bietet einige zusätzliche Funktionen:
Diese Shell-Optionen werden:
Andere interessante Möglichkeiten werden sich wahrscheinlich bieten.
quelle
Ich mag Alhadis Antwort am liebsten. Fügen Sie jedoch noch eine weitere Sache hinzu, um die Spaltenformatierung beizubehalten.
Ausgänge:
quelle
make
, erwartet er im Allgemeinen, dass ein Erstellungsprozess gestartet wird.Nicht vollständig mit dem OP verbunden, aber hoffentlich hilft dies jemandem in Zukunft. (da diese Frage bei Google-Suchanfragen am häufigsten auftaucht).
In meinem Makefile wollte ich den Inhalt einer Datei an einen Docker-Build-Befehl übergeben. Nach viel Bestürzung entschied ich mich für:
siehe Beispiel unten.
nb: In meinem speziellen Fall wollte ich während des Image-Builds einen SSH-Schlüssel übergeben, indem ich das Beispiel von https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ (using) verwendete ein mehrstufiger Docker-Build, um ein Git-Repo zu klonen und dann den SSH-Schlüssel aus dem endgültigen Image in der 2. Phase des Builds zu entfernen)
Makefile
Dockerfile
quelle
Mit GNU Make 3.82 und höher ist die
.ONESHELL
Option Ihr Freund, wenn es um mehrzeilige Shell-Snippets geht. Wenn ich Hinweise aus anderen Antworten zusammenstelle, bekomme ich:Stellen Sie beim Kopieren und Einfügen des obigen Beispiels in Ihren Editor sicher, dass alle
<tab>
Zeichen erhalten bleiben, da sonst dasversion
Ziel beschädigt wird!Beachten Sie,
.ONESHELL
dass alle Ziele im Makefile eine einzige Shell für alle ihre Befehle verwenden.quelle
make version printf "Version 1.2.3 of foo-bar has been released. /bin/sh: 1: Syntax error: Unterminated quoted string make: *** [version] Error 2
(GNU machen 3,81)@printf ...
Anweisung - es sieht so aus, als würden TABs immer als 4 Leerzeichen gerendert ....ONESHELL
es neu in Marke 3.82 ist.*** missing separator. Stop.
.Keine wirklich hilfreiche Antwort, aber nur um anzuzeigen, dass 'define' nicht wie von Axe beantwortet funktioniert (passte nicht in einen Kommentar):
Es gibt einen Fehler, dass der Befehl 'It' nicht gefunden werden kann, daher wird versucht, die zweite Zeile von ANNOUNCE BODY als Befehl zu interpretieren.
quelle
Es hat bei mir funktioniert:
quelle
GNU Makefile kann Folgendes tun. Es ist hässlich und ich werde nicht sagen, dass Sie es tun sollten, aber ich tue es in bestimmten Situationen.
make .profile
Erstellt eine Profildatei, falls keine vorhanden ist.Diese Lösung wurde verwendet, wenn die Anwendung GNU Makefile nur in einer POSIX-Shell-Umgebung verwendet. Das Projekt ist kein Open Source-Projekt, bei dem die Plattformkompatibilität ein Problem darstellt.
Ziel war es, ein Makefile zu erstellen, das sowohl die Einrichtung als auch die Verwendung eines bestimmten Arbeitsbereichs erleichtert. Das Makefile bringt verschiedene einfache Ressourcen mit sich, ohne dass Dinge wie ein anderes spezielles Archiv usw. erforderlich sind. Es ist gewissermaßen ein Shell-Archiv. Eine Prozedur kann dann beispielsweise sagen, dass Sie dieses Makefile in den Ordner legen, in dem Sie arbeiten möchten. Richten Sie Ihren Arbeitsbereich ein
make workspace
, geben Sie dann blah, entermake blah
usw. ein.Was schwierig werden kann, ist herauszufinden, was zu zitieren ist. Das Obige erledigt den Job und kommt der Idee nahe, hier ein Dokument im Makefile anzugeben. Ob es eine gute Idee für den allgemeinen Gebrauch ist, ist eine ganz andere Frage.
quelle
Ich glaube, die sicherste Antwort für die plattformübergreifende Verwendung wäre die Verwendung eines Echos pro Zeile:
Dadurch wird vermieden, dass Annahmen über die Version des Echos verfügbar gemacht werden.
quelle
Verwenden Sie die Zeichenfolgenersetzung :
Dann in dein Rezept setzen
Dies funktioniert, weil Make alle Vorkommen von
|
(beachten Sie das Leerzeichen) ersetzt und durch ein Zeilenumbruchzeichen ($$'\n'
) ersetzt. Sie können sich die entsprechenden Shell-Skript-Aufrufe wie folgt vorstellen:Vor:
Nach dem:
Ich bin nicht sicher, ob
$'\n'
es auf Nicht-POSIX-Systemen verfügbar ist, aber wenn Sie Zugriff auf ein einzelnes Zeilenumbruchzeichen erhalten können (selbst wenn Sie eine Zeichenfolge aus einer externen Datei lesen), ist das zugrunde liegende Prinzip dasselbe.Wenn Sie viele Nachrichten wie diese haben, können Sie das Rauschen mithilfe eines Makros reduzieren :
Wo Sie es so aufrufen würden:
Hoffe das hilft jemandem. =)
quelle
Alternativ können Sie den Befehl printf verwenden. Dies ist unter OSX oder anderen Plattformen mit weniger Funktionen hilfreich.
So geben Sie einfach eine mehrzeilige Nachricht aus:
Wenn Sie versuchen, die Zeichenfolge als Argument an ein anderes Programm zu übergeben, können Sie dies folgendermaßen tun:
quelle