Wie bringe ich Makefile dazu, nur geänderte Dateien neu zu kompilieren?
Lesezeit: 8 Minuten
Pithikos
Ich habe mich ein wenig bemüht, make dazu zu bringen, nur die Dateien zu kompilieren, die bearbeitet wurden. Allerdings hatte ich nicht viel Erfolg und alle Dateien werden neu kompiliert. Kann mir jemand erklären warum?
Meine Dateien sind:
main.c
a_functions.c
wo Haupt c beinhaltet main.h
und a_funktionen.c beinhaltet Ah
@sarnold: bedeutet nur Suche nach Include-Dateien im aktuellen Verzeichnis sowie nach implementierungsdefinierten. Ob es nötig ist, ist fraglich, aber ich glaube nicht, dass es schaden würde.
– paxdiablo
19. Oktober 2011 um 0:58 Uhr
@paxdiablo vielleicht, aber ich vermute, es ist ein Symptom für ein anderes Problem. Wenn seine Plattform keine systemweiten Header für etwas bereitstellt und er seine eigenen Versionen bereitstellen muss, ist das eine Sache, aber ich schätze, es ist so wie es ist ein Fehler …
– Sarnold
19. Oktober 2011 um 1:02 Uhr
@sarnold: Wie kann das ein Fehler sein? Es wird mit ziemlicher Sicherheit Header-Dateien geben, die in so ziemlich jedem Programm, das Sie jemals kompilieren möchten, in das aktuelle Verzeichnis aufgenommen werden müssen.
– Famarri
19. Oktober 2011 um 1:04 Uhr
Es ist keine gute Idee, Fragen so zu ändern, dass die Antworten ungültig werden. Fühlen sich frei vermehren Die Informationen (siehe meine Bearbeitung) sonst wird SO viel weniger nützlich, da die Antworten nicht mit den Fragen übereinstimmen.
– paxdiablo
19. Oktober 2011 um 1:32 Uhr
Beta
Das spezifische Problem, von dem Sie sprechen — Machen Sie Neuerstellungen program1 (durch Neuverknüpfung der Objekte) auch wenn sich nichts geändert hat — ist in dieser Regel:
Das Ziel dieser Regel ist program, und Make geht davon aus, dass es sich um eine Datei handelt. Aber da es keine solche Datei gibt, denkt Make jedes Mal, wenn Sie Make ausführen, dass diese Datei neu erstellt werden muss, und führt die Regel aus. Ich schlage vor:
Es macht keinen Sinn, diese Objekte miteinander zu verknüpfen, es sei denn, etwas in einem (wahrscheinlich main.o) ruft etwas im anderen (wahrscheinlich a_functions.o), also würde ich erwarten, eine Abhängigkeit wie diese zu sehen:
main.o: a.h
Ich vermute also, dass Sie einige unangebrachte Erklärungen haben.
Du erklärst ein objects Regel, aber beziehen Sie sich nie darauf. Sie verwenden es also nie wirklich; Make verwendet die Standardregel für %.o: %.c. Ich schlage vor:
Guter Fang, +1, ich denke, wir haben einen Gewinner.
– paxdiablo
19. Oktober 2011 um 3:29 Uhr
Hätte .PHONY geholfen? (Wahrscheinlich aber ein GNU-Make-Only-Feature.)
– David Poole
24. Oktober 2011 um 20:55 Uhr
@DavidPoole, konzeptionell ja, es würde Make that sagen program wird nicht als Datei erwartet (und sollte ausgeführt werden, selbst wenn eine solche Datei existiert). Praktisch nein, da Make diese Regel immer noch ausführen würde, selbst wenn sich nichts geändert hätte.
– Beta
25. Oktober 2011 um 3:11 Uhr
Vielen Dank. Ich sehe jetzt wie $(OBJECTS): %.c macht keinen Sinn. Also die Regel %.o: %.c<newline><TAB>$(CC) $< $(CFLAGS) -o [email protected] bedeutet “für jede .c-Datei die entsprechende .o-Objektdatei kompilieren”. Und die Regel $(OBJECTS): %: %.c<newline><TAB>$(CC) $< $(CFLAGS) -o [email protected] bedeutet “für jede .o-Datei in OBJECTS kompilieren Sie die entsprechende .c-Datei in eine .o-Objektdatei”.(?) – Ich bemerke eine Diskrepanz zwischen Ihrer $(OBJECTS): %: %.c und die $(objects): %.o: %.c in die Dokumente – Sie schreiben %.o wo du nur schreibst %. Schreibfehler? Oder beide gültig?
– Henke
8. Dezember 2020 um 10:14 Uhr
@Henke: Guter Fang, das war ein Tippfehler von mir — der neun Jahre lang niemandem aufgefallen ist! Ich werde bearbeiten.
– Beta
8. Dezember 2020 um 15:53 Uhr
paxdiablo
Nicht sicher, ob dies Ihr spezifisches Problem verursacht, aber die beiden Zeilen:
a_functions.c: a.h
main.c: main.h
sind definitiv falsch, da es im Allgemeinen keinen Befehl gibt, um eine C-Datei basierend auf einem darin enthaltenen Header neu zu erstellen.
C-Dateien hängen nicht von ihren Header-Dateien ab, die Objekte erstellt von diesen C-Dateien tun.
Zum Beispiel ein main.c von:
#include <hdr1.h>
#include <hdr2.h>
int main (void) { return 0; }
(vorausgesetzt, dass a_functions.c beinhaltet a.h und main.c beinhaltet main.h) und versuche es noch mal.
Wenn diese obige Annahme falsch ist, müssen Sie uns mitteilen, welche C-Dateien welche Header enthalten, damit wir Ihnen die richtigen Regeln mitteilen können.
Wenn Ihre Behauptung ist, dass die makefile auch nach diesen Änderungen immer noch alles baut, müssen Sie sich zwei Dinge ansehen.
Die erste ist die Ausgabe von ls -l auf alle relevanten Dateien, damit Sie sehen können, welche Daten und Uhrzeiten sie haben.
Die zweite ist die tatsächliche Ausgabe von make. Die Ausgabe von make -d wird da besonders hilfreich sein zeigt an welche Dateien und Daten make verwendet, um herauszufinden, was zu tun ist.
In Bezug auf die Untersuchung, make scheint nach folgendem Transkript gut zu funktionieren:
Ich habe getan, wie Sie gesagt haben, aber es wird immer noch alles neu kompiliert. Ich habe sogar versucht, Ihr Beispiel zu kopieren, indem ich main.o: main.c main.h \n $(CC) main.c $(CFLAGS) hatte, aber immer noch das gleiche Problem
– Pithikos
19. Oktober 2011 um 1:11 Uhr
@Pithikos: Zeigen Sie uns die Ausgabe des Compilers. Warum sagen Sie, dass es jedes Mal kompiliert wird.
– Famarri
19. Oktober 2011 um 1:20 Uhr
@Falmarri Ich kann sehen, dass es neu kompiliert wird, wenn sich das Datum von program1 jedes Mal ändert, wenn ich es mache.
– Pithikos
19. Oktober 2011 um 1:24 Uhr
Die Objekte werden nicht neu kompiliert. Es ist nur das Programm1, das neu verknüpft wird.
– Pithikos
19. Oktober 2011 um 1:40 Uhr
Eule
Dies sehr spät nach der Tatsache, und eigentlich basiert es auf der hervorragenden Antwort von paxdiablo, aber beim Experimentieren habe ich festgestellt, dass Sie keine separaten Ziele für jede .o-Datei benötigen, es sei denn, Sie tun etwas Cleveres.
Also für mein Makefile:
all: program
program: a_functions.o main.o
gcc a_functions.o main.o -o program
clean:
rm -f *.o
rm -f program
In make 4.1 werden die .o-Dateien automatisch kompiliert, Sie müssen nichts tun, wenn Ihre .o-Dateien dieselben Namen haben wie Ihre Quelldateien. Also wird es automatisch nach a_functions.c, a_functions.h, main.h und main.c suchen. Wenn Sie nicht die erwarteten Quellcodenamen haben, erhalten Sie eine Fehlermeldung wie:
make: *** No rule to make target 'a_functions.o', needed by 'program'. Stop.
Ich habe auch ein “sauberes” Ziel für Sie hinzugefügt. “Clean” ist nützlich, wenn Sie Ihre Software als Quellcode freigeben müssen oder einfach alle kompilierten Objektdateien und / oder Binärdateien entfernen möchten.
Und das ist alles, was Sie tun müssen.
Speichern Sie dies in “Makefile” und führen Sie Folgendes aus:
$ make
um Ihre Binärdatei zu erstellen. Und
$ make clean
um die kompilierten Objekte und Binärdateien in Ihrem Code zu bereinigen.
14177400cookie-checkWie bringe ich Makefile dazu, nur geänderte Dateien neu zu kompilieren?yes
-I.
kommt mir seltsam vor. Was ist damit?– Sarnold
19. Oktober 2011 um 0:56 Uhr
@sarnold: bedeutet nur Suche nach Include-Dateien im aktuellen Verzeichnis sowie nach implementierungsdefinierten. Ob es nötig ist, ist fraglich, aber ich glaube nicht, dass es schaden würde.
– paxdiablo
19. Oktober 2011 um 0:58 Uhr
@paxdiablo vielleicht, aber ich vermute, es ist ein Symptom für ein anderes Problem. Wenn seine Plattform keine systemweiten Header für etwas bereitstellt und er seine eigenen Versionen bereitstellen muss, ist das eine Sache, aber ich schätze, es ist so wie es ist ein Fehler …
– Sarnold
19. Oktober 2011 um 1:02 Uhr
@sarnold: Wie kann das ein Fehler sein? Es wird mit ziemlicher Sicherheit Header-Dateien geben, die in so ziemlich jedem Programm, das Sie jemals kompilieren möchten, in das aktuelle Verzeichnis aufgenommen werden müssen.
– Famarri
19. Oktober 2011 um 1:04 Uhr
Es ist keine gute Idee, Fragen so zu ändern, dass die Antworten ungültig werden. Fühlen sich frei vermehren Die Informationen (siehe meine Bearbeitung) sonst wird SO viel weniger nützlich, da die Antworten nicht mit den Fragen übereinstimmen.
– paxdiablo
19. Oktober 2011 um 1:32 Uhr