Makefile mit Verzeichnisbaumerstellung, die für paralleles (-j) Build geeignet ist

7

Mein Projekt benötigt temporäre Verzeichnisse, die während des Builds mit mkdir -p ähnlich wie folgt erstellt werden:

%Vor%

Aber dieser Ansatz kann nicht mit der Option -j verwendet werden, weil die ersten OBJFILES kompiliert werden, bevor das Ziel mkdir erstellt wird.

Gibt es eine Standardmethode?

    
danatel 12.12.2009, 19:22
quelle

3 Antworten

14

Das Problem mit Ihrem Makefile ist, dass die Erstellung Ihrer Objektdateien nicht von der Erstellung der relevanten Verzeichnisse abhängt (nur ein falsches "All" -Ziel). Diese Art von Abhängigkeit ist für -j -Option notwendig, und auch ohne sie funktioniert Ihr Makefile nur zufällig. Es gibt zwei (richtige) Möglichkeiten, die Abhängigkeit in Frage zu stellen.

Verzeichnisse als separate Ziele

Sie haben das Ziel für die Verzeichniserstellung erstellt. Was übrig ist, wird nur als Voraussetzung für die Objektdateiregel angegeben:

%Vor%

Das Pipe-Symbol% ​​co_de% bedeutet, dass dirtree eine "Nur-Voraussetzung" . Es wird verwendet, wenn "dirtree" eine Voraussetzung ist, aber Änderungen in der dirtree nicht Objektdateien ungültig machen und das Ergebnis des Kompilierungsbefehls nicht beeinflussen.

Die Verwendung der "Nur-Bestellung" -Voraussetzung ist hier wichtig. Die Sache ist, dass | target bei jedem Make-Aufruf neu erstellt wird. Das würde dazu führen, dass alles, was davon abhängt, neu erstellt wird, so dass jedes Mal alle Objektdateien neu erstellt werden.

Erstellen Sie Verzeichnisse in Shell-Befehlen

Sie können auch sicherstellen, dass das Verzeichnis unmittelbar vor dem Aufrufen der Kompilierung erstellt wird.

%Vor%

Beachten Sie die Verwendung von dirtree . Dies wird als "das Verzeichnis für die Zieldatei" erweitert. So kann es an vielen Stellen und sogar mit Hilfe einer Variablen einheitlich verwendet werden.

%Vor%

Beide Möglichkeiten stellen sicher, dass das Verzeichnis erstellt wird, bevor die Kompilierungsbefehle aufgerufen werden. In beiden Fällen müssen Sie für jede Regel, die sie benötigt, einen Text schreiben (entweder $(@D) oder | dirtree ). Beide Möglichkeiten sind $(Mkdir) kompatibel, aber die zweite Lösung erfordert -j threadsicher (da zwei solche Befehle gleichzeitig versuchen könnten, das gleiche Verzeichnis zu erstellen, und eines davon würde fehlschlagen).

Während die meisten Systeme es so implementieren, dass mkdir -p auf einigen Systemen mehr oder weniger Thread-sicher ist ( wie in einigen Solaris-Systemen, zum Beispiel ), sind sie weniger Thread-sicher als die anderen. Aber selbst in der GNU-Toolchain kann mkdir -p fehlschlagen, wenn sie gleichzeitig den gleichen mkdir -p -Bibliotheksaufruf aufrufen.

Wenn Sie sehr sicher sein wollen, können Sie das auch tun. Was könnte das Problem sein? Diese zwei mkdir(2) -Skripts versuchen, das gleiche Verzeichnis zu erstellen und irgendwo in der C-Bibliothek zu kollidieren. Dann wird einer dieser mkdir -p -s erfolgreich sein und der andere wird fehlschlagen. Wenn das von Ihnen aufgerufene mkdir jedoch fehlgeschlagen ist, kann es nur dann zu einem Thread-unsafety-bedingten Fehler kommen, wenn das Verzeichnis von einem gleichzeitigen mkdir erstellt wurde. Es wäre also ausreichend, einfach zu überprüfen, ob das Zielverzeichnis nach mkdir Aufruf erstellt wurde:

%Vor%

(Diese Lösung hat auch ein Problem mit dem Modus: mkdir kann fehlschlagen, wenn ein Verzeichnis existiert, aber nicht mit umask übereinstimmt, also sollten Sie das ebenfalls überprüfen. Aber das ist zu viel, denke ich.)

    
Pavel Shved 14.12.2009, 17:29
quelle
4

Ich bin mir nicht sicher, ob ich deine Frage vollständig verstanden habe. Ich kann jedoch Folgendes sagen: Wenn Ihr Build beim Hinzufügen von Parallelität abbricht, ist dies ein Hinweis darauf, dass Sie die Abhängigkeiten nicht korrekt definiert haben. Fragen Sie sich: "Müssen die Verzeichnisse vorhanden sein, bevor die Objektdateien generiert werden?" Wenn die Antwort "Ja" lautet, sollten die Verzeichnisse als Voraussetzungen der Objektdateien aufgelistet werden. Mit anderen Worten:

%Vor%

Und ja, das ist so ziemlich der übliche Weg, dies zu tun:)

    
Dan Moulding 12.12.2009 19:50
quelle
2

Sie könnten die Regeln zum Erstellen der Objektdateien mit dem Namen mkdir -p als erste Aktion haben.

    
ndim 12.12.2009 19:40
quelle

Tags und Links