2010-08-19 6 views
12

make Syntax ist newline-delimited, aber $ (shell ...) ersetzt newlines durch whitespace. Also, was ist die am wenigsten hässliche Art und Weise

$ (eval $ (Shell-Programm-that-abstrahlt-Makefile-Fragment))

zu tun, das nicht die Art und Weise funktioniert eine vielleicht gefallen.

Antwort

13

Dies wird wahrscheinlich tun, was Sie im Sinn haben:

makefile_fragment: 
    program-that-emits-makefile-fragment > [email protected] 

include makefile_fragment 

dass genug? Es gibt zusätzliche Tricks, die Sie verwenden können, wenn Sie sie benötigen, z. B. dass die Regel Kontext um das Programm herum hinzufügt oder die Ausgabe über sed in eine Zeile gleitet und dann mit umgekehrten Schrägstrichen analysiert.

+3

+10 wenn ich könnte. Das ist eine elegante und tragbare Lösung. –

+0

Funktioniert nicht .. _für mich_. Ich bekomme nur Variationen über 'make:" makefile_fragment "ist auf dem neuesten Stand. –

+0

alex grey: probiere [eine Abhängigkeit vom Makefile selbst] (http://make.mad-scientist.net/constructed-include-) files /) - 'makefile_fragment: $ (MAKEFILE_LIST)' – rampion

4

Das Thema wurde bereits auf die GNU berichtet machen Maintainer:

http://savannah.gnu.org/bugs/?28230

Es wurde mit dem folgenden Kommentar:

Als Philip erwähnt, ist dies die beabsichtigte/dokumentierte Verhalten .
Ich empfehle die Verwendung von "include" statt eval; Lassen Sie Ihr Skript eine Datei schreiben und fügen Sie diese Datei hinzu.

ADDED: Es gibt eine Abhilfe! Hier ist ein Beispiel GNUmakefile (ersetzen 8 Leerzeichen durch Tabulatoren, ja, gibt es zwei leere Zeilen nach define newline):

define newline 


endef 

$(eval $(subst #,$(newline),$(shell { echo 'war:'; echo '  echo "not love?"'; echo '  echo "Give peace a chance!"'; } | tr '\n' '#'))) 

Allgemeiner gesagt, das ist $(eval $(subst #,$(newline),$(shell myscript | tr '\n' '#')))

Sie haben ein Zeichen wählen, die nicht angezeigt wird die Ausgabe des Skripts; # scheint ein guter Kandidat zu sein.

+0

Das Schreiben von Dateien ist ein bisschen hässlich --- muss tempfile verwenden, um etwas zu verhindern, sauber zu machen, etc. Folgendes funktioniert so lange wie die Zeilen von der Skript enthält kein Leerzeichen. $ (Foreach-Zeile, $ (Shell-Make-Frag-Maker), $ (eval $ (Zeile))) – Bryan

+0

@colmode: Wenn Sie nicht die Include-Trick, hier ist ein anderer. Ich bin mir nicht sicher, ob ich es mag: es fühlt sich sehr hacky an, aber auf der anderen Seite ist es das, was ich sonst erwartet habe. Ein guter Punkt ist, dass es ziemlich transparent ist; Ein Pluspunkt von Includes ist, dass sie ein wenig einfacher zu debuggen sein sollten. – Gilles

+0

Persönlich würde ich den "include" -Ansatz bevorzugen. Portabilität spielt im OP-Fall keine Rolle, aber "include" vermeidet die Verwendung nicht tragbarer Konstrukte (wie $ (shell) und $ (eval)) und ist daher meiner Meinung nach die bessere Lösung. –

0

Hier ist ein Weg, dies zu tun, indem Sie das% Substitutionszeichen übernehmen, so dass wir uns nicht auf ein Zeichen verlassen müssen, das nicht in der Ausgabe von myscript erscheint.

define nl 


enddef 
$(foreach line, $(shell myscript | sed -e 's/%/\\%/' -e 's/$$/%/'), \ 
    $(eval $(patsubst %, $(line), $(nl)))) 
+0

Funktioniert nicht für mich, auch nach s/enddef/endef /: 'GNUmakefile: 5: *** fehlt Trennzeichen. Stop. (GNU Make 3.81) – Gilles

+0

Neugierig. Ich habe es gerade aus diesem Post wieder in das Makefile eingefügt und es funktioniert für mich. Gleiche Version von make, too. Ist es möglich, dass dieser Parsing-Fehler von der Ausführung des Evals kommt, d. H. Es ist ein Fehler in der Ausgabe von myscript? – Bryan