2016-08-29 3 views
1

Mit make '' Remaking Makefiles '' Funktion erzeuge ich Teile meines Makefiles mit include Direktiven (siehe Makefile: defining rules and prerequisites in recipes). Jetzt bin ich nicht mehr in der Lage zu sehen, wie ich Abhängigkeiten zwischen enthaltenen Makefiles ausdrücken kann. Sie scheinen alle gleichzeitig ausgewertet zu werden.Makefile: Abhängigkeiten zwischen eingebundenen Dateien deklarieren

die folgende minimale Make-Datei Man bedenke, dass mein Problem zeigt:

all: 

-include foo.make 
-include bar.make 

foo.make: Makefile 
    echo FOO:=blub bla baz > foo.make 

bar.make: Makefile foo.make 
    echo BAR:=$(FOO) > bar.make 

Wenn ich jetzt make betreibe ich bekommen:

$ cat foo.make 
FOO:=blub bla baz 
$ cat bar.make 
BAR:= 

Warum? Da bar.make von foo.make abhängt, sollte nicht die Auswertung von bar.make warten, bis es erfolgreich foo.make enthalten?

Und wie behebe ich dieses Problem und stellen Sie sicher, dass bar.make entweder neu bewertet oder erst einmal ausgewertet foo.make existiert, ist enthalten und kann die Variable BAR definieren?

Der Grund, warum ich nicht foo.make und bar.make in eine einzige Make-Datei und Regel ist zweifach kombinieren:

Zum einen in meinem wirklichen Setup hängt bar.make mehrere Zwischenziele auf die transitively wiederum auf foo.make abhängen. So kann zur Zeit foo.make erstellt werden, der Inhalt von bar.make kann noch nicht erstellt werden.

Zweitens, in meinem realen Setup, foo.make und bar.make nicht nur Variablen definieren, sondern auch eval()define/endef Blöcke. Also muss ich schreiben:

-include makefile_with_prerequisite_variables 
define MYDEF 
sometarget-$1: $(TARGET_$1_PREREQUISITES) 
    [...] 
endf 
-include makefile_with_eval_call_statements 

Der Gehalt an makefile_with_prerequisite_variables und makefile_with_eval_call_statements nicht in einem einzigen Makefile-Schnipsel gehen kann:

  • Wenn ich makefile_with_eval_call_statementsobenMYDEF zusammen mit makefile_with_prerequisite_variables dann die $eval($call(MYDEF)) Aussagen setzen würde in es würde nicht funktionieren, weil MYDEF nur danach deklariert wird.
  • Wenn ich makefile_with_prerequisite_variablesunterMYDEF zusammen mit makefile_with_eval_call_statements dann die Rezepte in MYDEF definiert setzen würde hätte nicht richtig VORAUSSETZUNGEN, weil die $(TARGET_$1_PREREQUISITES) Variablen dann danach von makefile_with_prerequisite_variables erklärt werden würde.

Zusammenfassend muss ich zwei verschiedene makefiles einschließen, wo man auf dem anderen abhängt. Ich weiß nicht, wie ich diese Beziehung so ausdrücken kann, dass der Inhalt eines Makefiles erst erstellt wird, nachdem das andere Makefile auf dem neuesten Stand ist und in das Makefile aufgenommen wurde.

Antwort

1

Zuerst kann Ihre Makefile-Erstellung in diesem einfachen Beispiel leicht behoben werden, indem Sie den Wert $(FOO) so umgehen, dass es nicht erweitert wird, wenn bar.make erstellt wird, sondern verzögert, bis es eingelesen wird.Also:

bar.make: Makefile foo.make 
     echo 'BAR:=$$(FOO)' > [email protected] 

Allerdings könnte das in Ihren komplexeren realen Makefiles nicht ausreichen.

GNU machen funktioniert so: zuerst alle Makefiles analysieren. Dann behandle es für jedes eingeschlossene Makefile als ein Ziel und versuche, es aufzubauen (z. B. handle so, als ob der Benutzer make include1.mk include2.mk include3.mk ... aufgerufen hätte). Wenn dann eines der enthaltenen Makefiles neu erstellt wurde, führen Sie die Ausführung erneut aus und starten Sie den gesamten Prozess von vorne.

GNU machen tut NICHT funktionieren wie folgt: Pars Makefiles, versuchen, das erste enthaltene Makefile neu zu erstellen und wenn es umgebaut wird, Re-Exec; wenn es nicht wieder aufgebaut ist, um zum nächsten weitergehen inklusive Make-Datei usw.

Ein einfacher Trick, den Sie verwenden können, wenn Sie diese Art von Ordnung haben müssen, ist auf die Include setzen bar.make in foo.make:

all: 

-include foo.make 

foo.make: Makefile 
     printf -- '-include bar.make' > [email protected] 
     echo FOO:=blub bla baz >> [email protected] 

bar.make: Makefile foo.make 
     echo 'BAR:=$$(FOO)' > [email protected] 

Auf diese Weise stellen Sie sicher, dass, wenn foo.make nicht existiert, make das Include bar.make nicht sehen kann und es nicht versuchen wird, es zu erstellen. Erst nach dem ersten Re-Exec wird das Include von bar.make erscheinen und versuchen, es zu bauen.

Eine Sache: Wenn Sie die neueste Version von GNU bekommen, müssen Sie nicht mehr den -include Trick verwenden. Sie können einfach include auch mit generierten Makefiles verwenden.

+0

Sie haben meinen Tag noch einmal gerettet! Wenn ich Ihnen mehr Upvotes geben könnte, würde ich es tun. Beide Vorschläge sind sehr wertvoll. Danke vielmals! – josch

Verwandte Themen