2008-11-26 14 views
21

Ich benutze (GNU) Make in meinem Projekt. Ich setze gerade ein Makefile pro Verzeichnis und spezifiziere die Unterverzeichnisse, die SUBDIRS verwenden. Es wurde mir vorgeschlagen, dass dies nicht der ideale Weg ist, make zu verwenden, das eine Toplevel-make-Datei verwendet (oder mehrere, die mit include geteilt werden). Ich habe versucht, dieses Layout in der Vergangenheit zu migrieren/zu verwenden, aber es scheint mir, dass es unnötig kompliziert ist.Rekursive Make - Freund oder Feind?

Welche Vorteile/Nachteile hat die Verwendung von rekursiven Makefiles?

Antwort

22

Das erste, was Sie beachten sollten (um Missverständnisse zu vermeiden), ist, dass es sich nicht um ein einzelnes vs. mehrere Makefiles handelt. Es ist in jedem Fall eine gute Idee, das Makefile in einem Unterverzeichnis zu teilen.

Rekursive Makefiles sind in erster Linie schlecht, weil Sie Ihren Abhängigkeitsbaum in mehrere Bäume partitionieren. Dies verhindert, dass Abhängigkeiten zwischen make-Instanzen korrekt ausgedrückt werden. Dies führt auch dazu, dass (teilweise) der Abhängigkeitsbaum mehrere Male neu berechnet wird, was letztendlich ein Leistungsproblem darstellt (wenn auch normalerweise kein großer).

Es gibt ein paar Tricks, die Sie verwenden müssen, um Verwenden Sie den Single-Make-Ansatz richtig, besonders, wenn Sie eine große Codebasis haben:

Zuerst verwenden Sie GNU make (Sie bereits tun, sehe ich). GNU make hat eine Reihe von Funktionen, die die Dinge vereinfachen, und Sie müssen sich nicht um Kompatibilitäten kümmern.

Zweitens, verwenden Sie zielspezifische Variablenwerte.Dies ermöglicht es Ihnen zu haben, beispielsweise verschiedene Werte von CFLAGS für verschiedene Ziele, anstatt Sie zu zwingen, eine einzige CFLAGS in Ihrer gesamten Make haben:

main: CFLAGS=-O2 
lib: CFLAGS=-O2 -g 

Drittens, stellen Sie sicher VPATH/vpath auf die Verwendung volles Ausmaß unterstützt von GNU make.

Sie möchten auch sicherstellen, dass Sie nicht mehrere Quelldateien mit demselben Namen haben. Eine Einschränkung von VPATH besteht darin, dass Sie keine zielspezifischen VPATH-Definitionen haben, sodass die Namen Ihrer Quelldateien in einem einzigen "VPATH-Namespace" nebeneinander bestehen müssen.

+0

Große Antwort, danke! Ich benutze VPATH sogar für ein Projekt mit rekursiven make-Dateien, das macht es viel einfacher, besonders für srcdir! = Builddir builds. –

0

Der Vorteil, den ich in der Vergangenheit daraus gezogen habe, ist, dass es einfacher ist, Dateien in einem einzigen Unterverzeichnis zu erstellen. Sie können dies mit Abhängigkeiten tun, aber es ist ein bisschen mehr Arbeit, um alle Ziele in Ordnung zu halten. Dies macht es einfacher, Änderungen vorzunehmen und eine Bibliothek zu testen, ohne sich mit der Komplexität des größeren Projekts auseinandersetzen zu müssen.

+0

Sie haben Recht. Einfachere Wiederverwendung gemeinsamer Ziele ist ein weiterer Vorteil –

-1

Das Problem mit rekursivem make ist der Zeitaufwand beim Auswerten aller verschiedenen make-Dateien im Vergleich zum Auswerten einer großen make-Datei. Ein Teil davon sind nur Laichprozesse, aber auch (IIRC) du wirst dazu gezwungen, anzunehmen, dass andere Dateien etwas machen und neu aufbauen, wenn du es nicht wirklich brauchst.

Meine Annahme ist es, eine einzige make-Datei pro "Unit" zu haben, die mehr oder weniger dazu führt, dass eine make-Datei für jeden Codeabschnitt, den man erwartet, alleine verwendet werden könnte (zB als unabhängige Bibliothek))

OTOH mein aktuelles Projekt bricht das überall auf, da ich während des Builds make-Dateien erzeuge. : b

+1

Nein, Zeit ist nicht das größte Problem. Das größte Problem besteht darin, den Abhängigkeitsbaum in mehrere Abhängigkeitsbäume zu gliedern, was verhindert, dass Abhängigkeiten zwischen den Untertypen korrekt ausgedrückt werden. – JesperE

+3

IMNSHO der einzige Grund, warum Sie sich überhaupt überhaupt um Abhängigkeiten kümmern * ist * Zeit. Wenn Sie sich nicht um die Zeit kümmern, machen Sie einfach einen von Grund auf neuen, leeren Schiefer jedes Mal neu aufzubauen. Sie können "korrekte" Abhängigkeiten erhalten, die durch Codierung ausgedrückt werden. Wenn sich etwas ändert, wird angenommen, dass sich alles geändert hat, aber es dauert länger. – BCS

17

Ein Artikel mit dem Titel "Rekursives Make Considered Harmful" finden Sie hier: http://miller.emu.id.au/pmiller/books/rmch/?ref=DDiyet.Com. (Oder unter Aegis Projekt bei SourceForge.)

Es erkundet die Probleme mit rekursiven Makefiles und empfiehlt einen Single-Makefile-Ansatz.

+0

Das ist eine gute Referenz, danke für den Hinweis. –

+0

Leider gibt der Link zum eigentlichen Papier eine 500. –

+0

Der Link zum Papier scheint jetzt in Ordnung zu sein. –

0

Um eine dritte Option hinzuzufügen, könnten Sie GNU Autotools verwenden. Meist aus anderen Gründen verwendet, kann aber auch hilfreich bei der Organisation eines Multi-Verzeichnis Build sein.

http://www.lrde.epita.fr/~adl/autotools.html

Es ist zu beachten Sie jedoch, dass das Ergebnis eine rekursive Version.

+0

Ich benutze tatsächlich Autotools, aber Sie können rekursive und nicht-rekursive Modus verwenden. –

4

Laufen Sie, gehen Sie nicht, zu cmake.org und erhalten Cmake, eines der besten Build-Tools zur Verfügung.

Sie werden immer noch GNU make verwenden, aber in diesem Fall generiert CMake die Makefiles für Sie.

Ich kann nicht 100% garantieren, aber ich bin noch auf einen Fall gestoßen, wo es Abhängigkeiten zwischen Unterverzeichnissen nicht korrekt behandelt hat (dh das Problem, das die rekursive Marke plagt). Zumindest ist es viel einfacher, Cmakefiles als Makefiles zu verwalten. Sehr empfehlenswert.

Verwenden Sie keine GNU-Autotools - so liegt Wahnsinn!

+1

Ich kenne die GNU-Autotools bereits zu gut und werde immer älter, um ein neues System zu lernen. Vielleicht in weiteren 5 Jahren :-) –

+3

CMake ist den Aufwand wert, um zu lernen. Es ist viel einfacher als Autotools, und die plattformübergreifende Unterstützung ist viel besser. –

+8

Ich habe gefunden, um eine viel seichtere Lernkurve als CMake zu haben. CMake's Syntax ist in ständiger Bewegung, die Dokumentation ist schrecklich, und am Ende ist es immer noch nicht in der Lage, automatisch die Standorte der gemeinsamen Bibliotheken auf Systemen zu finden, so dass Sie ständig nach "FindLibraryXYZ.CMake" cmake scripts suchen Projekt. Es gibt nichts Elegantes daran, also benutze es nur, wenn du es wirklich brauchst. Entschuldigung für die Tirade. –

1

Makepp ist dein Freund.

http://makepp.sourceforge.net/

  • rückwärts kompatibel mit Make
  • Automatisches Scannen nach Header-Abhängigkeiten
  • Graceful Umgang mit Verzeichnisbäume
5

ich ausgiebig Rekursion verwenden. jeder Blattknoten eine eigene Make-Datei haben, betrachten:

$LIBS = libfoo libbar 
$(LIBS): 
    cd [email protected] && $(MAKE) 

Auf großen Systemen ist es eine ziemliche Herausforderung sein würde, nicht um diese Struktur zu haben. Was Leute über "rekursive machen als schädlich" reden, ist eine genaue Einschätzung. Ich denke jede Situation ist ein bisschen anders und wir machen ein paar Kompromisse.