Makefile: multi-line variable substitution

Hello,

gerade versuche ich ein Makefile für ein kleines Projekt zu verbessern. Unter anderem benötige ich eine description_file welche einen Abschnitt enthält wie folgt (in diesem Fall 6 MD5-Summen, aber das ist nebensächlich):

~\>cat description\_file
[MD5]
filename1 = 3405DA45BFA456
filename2 = 3405FA45BFA405
filename3 = 58705DA468BFA4

Wenn ich das Project übersetze, generiere ich zuerst die Dateien (das funktioniert) mit code in der Makefile ungefähr wie

FILENAMES = filename1 filename2 filename3

all:
 for i in $(FILENAMES) do; ; done

es funktioniert auch, einzelne Variablen durch einen Einzel-String zu ersetzen:

sed s/{{VERSION}}/'$(GRF\_VERSION)'/ _inputfilename_ | sed s/{{NAME}}/'$(GRF\_NAME)'/ \> _processed\_filename_

Das könnte ich dann durch Pipes aneinanderhängen, um für jede Datei eine eigene Variable einzuführen und separat zu ersetzen. Allerdings würde ich das ganze gerne in einer For-Schleife machen, um sich wiederholenden Code zu vermeiden, der auch schnell unübersichtlich wird und an vielen Stellen auch angepaßt werden muß, wenn eine Datei hinzukommt oder sich die Dateinamen ändern.

Ich würde also gerne etwas ungefähr wie

cat $(_inputfilename_) | sed s/VARNAME/'for i in $(FILENAMES) do; echo `md5sum $$i`/ \> _processed\_description\_file_

umsetzen. Irgendwelche Ideen wie ich das umsetzen könnte?
Die Versuche mir bspw. eine mehrzeilige Variable mittels solcher For-Schleife zu generieren waren alle nicht von Erfolg gekrönt. Entweder blieb die Variable leer oder ich bekam ein „command not found“, weil eine der MD5-Summen als Kommando versucht wurde zu interpretieren.

Das Ganze soll natürlich möglichst Plattform-unabhängig laufen :smile: - wobei auf Win MinGW / MSys verwendet wird (also m.E. keine große Einschränkung).

Gruß,
Ingo

makefile: wie Variable schreiben
Moin,

etwas weiter Herumprobieren zeigt mir, dass das Problem etwas fundamentaler ist:

blub : 
 tmp=$(shell hg parent | grep 'changeset')
 @echo "Temp: $(tmp)"

führt zu

\> make blub
tmp=changeset: 8:db9e704de2cd
/bin/sh: 8:db9e704de2cd: command not found
make: \*\*\* [blub] Error 127

Und irgendwie bin ich aus dem Makefile-Tutorial noch nicht schlau geworden…

Gruß,
Ingo

Moin,

etwas weiter Herumprobieren zeigt mir, dass das Problem etwas
fundamentaler ist:

tmp=$(shell hg parent | grep ‚changeset‘)

du musst aufpassen: Das Dollarzeichen hat für Make (wie auch für die Shell) eine besondere Bedeutung. Hier interpretiert Make das „$(shell …)“ als Aufruf der Make-Funktion „shell“, macht einen entsprechenden Shell-Aufruf und setzt das Ergebnis in die Zeile ein, die dann so aussieht:

tmp=changeset: 8:db9e704de2cd

Make ist nun mit der Bearbeitung der Zeile fertig und übergibt sie wie jede andere in dem Aktionsteil einer Make-Regel der Shell. Die interpretiert den ersten Teil bis zum Whitespace als Zuweisung einer Variablen, und versucht, das folgende Kommando mit dieser Umgebungsvariablen auszuführen, was natürlich das hier bringt:

/bin/sh: 8:db9e704de2cd: command not found

Das Problem ist also, dass die Shell nicht mehr sieht, dass alles von „changeset:“ bis „2cd“ ein zusammenhängender Wert sein sollte.

Lösen kannst du das Problem auf zwei Arten: Entweder spendierst du ein paar Anführungszeichen:

 tmp="$(shell hg parent | grep 'changeset')"

Die Shell sieht dann:

tmp="tmp=changeset: 8:db9e704de2cd"

Oder du überlässt das Ausführen von „hg parent | …“ der Shell. Dann musst du die Dollarzeichen schützen (durch Verdoppeln), damit sie nicht von Make interpretiert werden:

 tmp=$$(hg parent | grep 'changeset')

Die Shell sieht dann

tmp=$(hg parent | grep 'changeset')

Gruß

Andreas