Angenommen, ich habe ein Makefile mit der Regel
%.o: %.c
gcc -Wall -Iinclude ...
Ich möchte, dass * .o neu erstellt wird, wenn sich eine Header-Datei ändert. Anstatt eine Liste von Abhängigkeiten zu erstellen /include
, müssen alle Objekte im Verzeichnis neu erstellt werden, wenn sich eine Header-Datei ändert.
Ich kann mir keine gute Möglichkeit vorstellen, die Regel zu ändern, um dies zu berücksichtigen. Ich bin offen für Vorschläge. Bonuspunkte, wenn die Liste der Header nicht fest codiert sein muss
Antworten:
Wenn Sie einen GNU-Compiler verwenden, kann der Compiler eine Liste von Abhängigkeiten für Sie zusammenstellen. Makefile-Fragment:
oder
Wobei
SRCS
eine Variable auf Ihre gesamte Liste der Quelldateien verweist.Es gibt auch das Tool
makedepend
, aber es hat mir nie so gut gefallen wiegcc -MM
quelle
depend
nur ausgeführt werden, wenn sich die Quelldateien geändert haben? Es scheint jedes Mal zu laufen, egal ...build/file.o
.Die meisten Antworten sind überraschend kompliziert oder falsch. Einfache und robuste Beispiele wurden jedoch an anderer Stelle veröffentlicht [ codereview ]. Zugegeben, die vom gnu-Präprozessor bereitgestellten Optionen sind etwas verwirrend. Das Entfernen aller Verzeichnisse aus dem Build-Ziel mit
-MM
ist jedoch dokumentiert und kein Fehler [ gpp ]:Die (etwas neuere)
-MMD
Option ist wahrscheinlich das, was Sie wollen. Der Vollständigkeit halber ein Beispiel für ein Makefile, das mehrere src-Verzeichnisse unterstützt und Verzeichnisse mit einigen Kommentaren erstellt. Eine einfache Version ohne Build-Verzeichnisse finden Sie unter [ codereview ].Diese Methode funktioniert, weil bei mehreren Abhängigkeitslinien für ein einzelnes Ziel die Abhängigkeiten einfach verbunden werden, z.
ist äquivalent zu:
wie unter: Mehrere Abhängigkeitslinien für ein einzelnes Ziel erstellen?
quelle
CPP
sollte lesenCPPS
a.cpp
,b.cpp
) haben./src/
, würde diese Ersetzung dann nicht erfolgen$(OBJ)=./build/src/a.o ./build/src/b.o
?Wie ich hier gepostet habe, kann gcc Abhängigkeiten erstellen und gleichzeitig kompilieren:
Der Parameter '-MF' gibt eine Datei an, in der die Abhängigkeiten gespeichert werden sollen.
Der Bindestrich am Anfang von '-include' weist Make an, fortzufahren, wenn die .d-Datei nicht vorhanden ist (z. B. bei der ersten Kompilierung).
Beachten Sie, dass es in gcc einen Fehler bezüglich der Option -o zu geben scheint. Wenn Sie den Dateinamen des Objekts auf obj / _file__c.o setzen, enthält die generierte Datei .d weiterhin die Datei .o und nicht obj / _file__c.o.
quelle
man gcc
sagt-MM
impliziert-E
, was "nach der Vorverarbeitung stoppt". Sie benötigen-MMD
stattdessen: stackoverflow.com/a/30142139/895245Wie wäre es mit so etwas wie:
Sie können die Platzhalter auch direkt verwenden, aber ich finde, ich brauche sie an mehr als einem Ort.
Beachten Sie, dass dies nur bei kleinen Projekten gut funktioniert, da davon ausgegangen wird, dass jede Objektdatei von jeder Header-Datei abhängt.
quelle
make clean all
jedes Mal gleichbedeutend mit dem Ausführen sein.gcc
Zeile wird überhaupt nicht ausgeführt, sondern stattdessen die integrierte Regel (%o: %.c
Regel).Martins obige Lösung funktioniert hervorragend, verarbeitet jedoch keine .o-Dateien, die sich in Unterverzeichnissen befinden. Godric weist darauf hin, dass das -MT-Flag dieses Problem behebt, aber gleichzeitig verhindert, dass die .o-Datei korrekt geschrieben wird. Das Folgende wird sich um diese beiden Probleme kümmern:
quelle
Dies erledigt den Job einwandfrei und behandelt sogar die angegebenen Unterverzeichnisse:
testete es mit gcc 4.8.3
quelle
Hier ist ein Zweiliner:
Dies funktioniert mit dem Standardrezept make, solange Sie eine Liste aller Ihrer Objektdateien in haben
OBJS
.quelle
Ich bevorzuge diese Lösung gegenüber der akzeptierten Antwort von Michael Williamson. Sie erfasst Änderungen an Quellen + Inline-Dateien, dann an Quellen + Headern und schließlich nur an Quellen. Vorteil hierbei ist, dass die gesamte Bibliothek nicht neu kompiliert wird, wenn nur wenige Änderungen vorgenommen werden. Keine große Überlegung für ein Projekt mit ein paar Dateien, aber wenn Sie 10 oder 100 Quellen haben, werden Sie den Unterschied bemerken.
quelle
Folgendes funktioniert für mich:
quelle
Eine leicht modifizierte Version von Sophies Antwort , mit der die * .d-Dateien in einem anderen Ordner ausgegeben werden können (ich werde nur den interessanten Teil einfügen, der die Abhängigkeitsdateien generiert):
Beachten Sie, dass der Parameter
wird verwendet, um sicherzustellen, dass die Ziele (dh die Objektdateinamen) in den generierten * .d-Dateien den vollständigen Pfad zu den * .o-Dateien und nicht nur den Dateinamen enthalten.
Ich weiß nicht, warum dieser Parameter NICHT benötigt wird, wenn -MMD in Kombination mit -c verwendet wird (wie in Sophies Version ). In dieser Kombination scheint es den vollständigen Pfad der * .o-Dateien in die * .d-Dateien zu schreiben. Ohne diese Kombination schreibt -MMD auch nur die reinen Dateinamen ohne Verzeichniskomponenten in die * .d-Dateien. Vielleicht weiß jemand, warum -MMD in Kombination mit -c den vollständigen Pfad schreibt. Ich habe keinen Hinweis in der g ++ - Manpage gefunden.
quelle