makefile: multi-line variable substitution

Von: , Frage gestellt am Di, 26. Mai 2009

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; <processing commands>; 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 :) - wobei auf Win MinGW / MSys verwendet wird (also m.E. keine große Einschränkung).

Gruß,
Ingo

2 Antworten zu dieser Frage

  1. Antwort von nach einer Stunde 0 hilfreich
    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

    • Antwort von nach einem Tag 0 hilfreich
      Re: makefile: wie Variable schreiben

      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

Keine passende Antwort gefunden? Jetzt eigene Frage stellen!