Hallo,
ich habe ein AVR Project und beim erstellen
compiliert er immer alle in der config.mk eingetragenen
c-code Datein.
Ich möchte aber das er nur geänderte Datein neu
compiliert.
Mit welchen Parametern muss ich 'make' ausführen
oder was muss im 'Makefile' eingetragen sein
um nur neue Datein zu compilieren?
Danke
Das Makefile ist das Werkzeug um genau das zu machen.
Du brauchst da nichts spezielles eintragen.
Wenn Make nicht korrekt funktioniert, dann liegt das meistens daran,
dass deine Rechnerzeit nicht stimmt.
Make orientiert sich am Filedatum.
Ist das Datum zb. des Object-Files neuer als das des C-Source Code
Files, dann wird nachcompiliert. Hat aber zb das C File aus irgendeinem
Grund als Filedatum zb den 24. 12. 2200 (also weit in der Zukunft)
eingetragen, dann wird make dieses File immer nachcompilieren, den das
enstehende Object-File bekommt ja das heutige Datum (2010). Rein aus dem
Vergleich dieses Filedatums würde daher die paradoxe Situation folgern,
dass das Ergebnis des Compiliervorgangs schon wieder älter als der
Quellcode ist. Und daher wird Make dieses File beim nächsten Aufruf
schon wieder nachcompilieren.
Es gibt noch andere Fehlerszenarien. Aber wenn dein Makefile
einigermassen stimmt, dann ist so was die häufigste Ursache. Wobei dann
noch immer die Frage bleibt, warum stimmt eigentlich das File-Datum
nicht?
Das kann zb sein, weil irgendjemand an der Systemuhr gespielt hat bzw.
die Systemuhr nicht mehr stimmt.
Also: Die File-Daten aller *.c und *.h Files ansehen. Wenn eines davon
ein Datum in der Zukunft trägt, dann hast du den Übeltäter.
Karl heinz Buchegger schrieb:> Ist das Datum zb. des Object-Files neuer als das des C-Source Code> Files, dann wird nachcompiliert.
Das war wohl einer von der freudschen Sorte? Da fehlt als vorletztes
Wort doch sicher noch ein "nicht"?
Oder Deine Definition von "neuer" ist diametral der meinigen.
... schrieb:> Karl heinz Buchegger schrieb:>> Ist das Datum zb. des Object-Files neuer als das des C-Source Code>> Files, dann wird nachcompiliert.>> Das war wohl einer von der freudschen Sorte? Da fehlt als vorletztes> Wort doch sicher noch ein "nicht"?
Jo.
Danke für den Catch. Der ist tatsächlich sinnentstellend.
Hallo
und danke für die schnelle Antwort.
-Systemzeit ist I.O.
-Ich bin alle *.c und *.h files durchgegangen
kein Datum ist in der Zukunft.
Im anhang ist das makefile evtl. erkennt
jemand warum er immer alles neu erzeugt?
Das makefile ist von ATMEL und wurde von mir unter
"# create object files from C source files."
an die Visual C fehlerausgabe angepasst.
Kann mal jemand der mehr von Makefiles versteht als ich, folgendes
verifizieren:
Meines Erachtens besteht der Fehler darin, dass man zwar dem make
mitteilt, dass zb test.o von test.c abhängt. Da aber der Compileraufruf
die test.o in einem Subdirectory erzeugt ($OUTPUT) und make nicht weiß,
dass der Zusammenhang .o zu .c über dieses $OUTPUT Directory läuft,
sieht die Situation für make ständig so aus, dass zu einem .c File
ständig gar kein .o File existiert.
make verucht das zu einem test.c zugehörige test.o auf demselben
Verzeichnis zu finden, findet es nicht und wirft daher den Compiler an.
Der Compiler erzeugt aber das test.o in einem ganz anderen Verzeichnis,
so dass beim nächsten make-Lauf sich die Situation für make schon wieder
so präsentiert, dass das zu test.c gehörende test.o noch gar nicht
existiert (weil es am falschen Verzeichnis nachsieht)
bedeutet, daß es für jede .c-Datei eine Datei mit .o statt .c und sonst
(inklusive Verzeichnis) komplett gleichem Namen als Ziel gibt.
Dann heißt es aber:
Das klingt plausibel um das zu testen,
stellt sich mir jetzt die frage wie ich
avr-gcc mitteilen kann, das er im $(OUTPUT)
verzeichnis nach den *.o files sucht.
Ja, wenn man in ein separates Verzeichnis bauen will, kann man nicht
mit Suffixregeln arbeiten, denn die wollen ja immer eine Datei im
gleichen Pfad, nur mit anderem Suffix, erzeugen.
Man muss also für jede Objektdatei eine Regel bauen:
$(BUILDDIR)/foo.o: foo.c
$(CC) $(CFLAGS) -o $(BUILDDIR)/foo.o -c foo.c
$(BUILDDIR)/bar.o: bar.c
$(CC) $(CFLAGS) -o $(BUILDDIR)/bar.o -c bar.c
Kann sein, dass GNU make sowas mit irgendeinem nicht portablen Trick
kann, da kenne ich mich nicht so aus.
Solche Ärgerlichkeiten sind mit der Grund, warum Makefile-Generatoren
à la automake sich einer gewissen Beliebtheit erfreuen. Die erzeugen
ein derartiges Makefile aus einer einfacheren Beschreibung, sodass
man das nicht alles mit der Hand pflegen muss.
eine Möglichkeit des Eingreifens, das man dem Object File ein anderes
Verzeichnis unterjubelt. Dann könnte die Sache mit den Regeln wieder
funktionieren.
Aber mir gehts da wie Jörg: Da sind meine Kentnisse der Makefiles zu
beschränkt. Wenn ich früher Makefiles gemacht habe, dann hab ich da
keine solchen Rundumschlaglösungen ala 'Alle C Files sind zu
compilieren' benutzt sondern schön fein säuberlich aufgeführt was Sache
ist.
Das hat den Vorteil, dass man dann auch ein paar 'Leichen' in Form von
C-Files auf dem Verzeichnis liegen lassen kann, die nicht zum Projekt
gehören.
Aber viel wichtiger noch: Abhängigkeiten!
Das ein .o von einem .c abhängt ist zwar cool und richtig. Viel
wichtiger ist aber: von welchen anderen Files (Headern) hängt es noch
ab? Denn erst dann beginnt sich ein Makefile bezahlt zu machen, wenn ich
ein Header File ändere und make alle davon abhängigen Object Files neu
erstellt. Ohne dieses Können ist make nämlich eine zahnlose Kuh, die zu
nicht zu gebrauchen ist ausser zu: alles neu compilieren und eventuell
noch: hinter sich aufräumen.
> eine Möglichkeit des Eingreifens, das man dem Object File ein anderes> Verzeichnis unterjubelt.
Nö, das legt ja nur den Wert des Makros OBJECTS fest, der dann woanders
als $(OBJECTS) referenziert werden kann (vermutlich beim Linken).
Ich spare mir normalerweise einfach die Verrenkungen und compiliere
in das Verzeichnis, in dem auch die Quellen liegen. Die Quellen
werden ohnehin via VCS getrackt, damit ist das aktuelle Verzeichnis
gar nicht mehr so wesentlich, und außerdem wird halt das "clean"-
Target noch passend mit gepflegt, sodass man bei Bedarf einfach alle
generierten Dateien mal wegwerfen kann.
>> eine Möglichkeit des Eingreifens, das man dem Object File ein anderes>> Verzeichnis unterjubelt.>> Nö, das legt ja nur den Wert des Makros OBJECTS fest, der dann woanders> als $(OBJECTS) referenziert werden kann (vermutlich beim Linken).
Yep. Das EXE hängt von den $OBJECTS ab.
Damit kommen die Namen der Object-Files in die Abhängigkeitskette
hinein. Jedes einzelne File in $OBJECTS wiederrum ...
Ich merke gerade: dann würde er die C-Files am falschen Verzeichnis
suchen, weil ja für jede Object-Datei wieder nur die allgemeine Suffix
Regel existiert.
Du hast schon recht. An dieser Regel hängt es.
(Da sieht man wieder wieviel man vergisst. Diese IDE sind einfach zu
komfortabel geworden :-)
Ist 1. ein GNUismus und 2. nur die halbe Miete. Man kann damit die
compilierte Datei nicht in ein Unterverzeichnis generieren lassen,
dafür fehlt zumindest noch die Regel, die das ableitet. Lässt sich
daher nur benutzen, wenn auch das Makefile selbst im Build-Verzeichnis
steht. Der wesentliche Sinn eines Build-Verzeichnisses ist es aber,
dass man selbiges bei Bedarf einfach komplett entleeren kann, was mit
dem Makefile drin natürlich nicht mehr klappt.
Florian hat sowohl die allgemeine Regel über/neu geschrieben, als auch
die Regel für "clean" nach seinen Bedürfnissen angepasst. Das ganze
Makefile sieht so aus, als ob es mit den Quelldateien im gleichen
Verzeichniss liegt. Damit sollte VPATH bei ihm den gewünchten Effekt
zeigen. Vorrausgesetzt er benutzt das GNU-Make.
Ja, nachdem ich mir die Beschreibung von VPATH nochmal angeguckt
habe, könnte das passen. Sieht aber alles ziemlich zusammengeklaubt
aus, selbst den alten AVR-Studio-Bug, beim CC noch das .exe mit
anzugeben (völlig überflüssig und unportabel zu GNU make auf nicht-
Windows-Plattformen) findet man wieder.
Allerdings sind nirgends Quelldateien angegeben; ich denke, man
müsste mindestens noch CSRCS irgendwo setzen.
Ich teste das morgen mal mit der VPATH variable!
@Jörg Wunsch
Das file ist nicht "zusammengeklaubt" ;) sondern von
ATMEL siehe post weiter oben..
>Das makefile ist von ATMEL und wurde von mir unter>"# create object files from C source files.">an die Visual C fehlerausgabe angepasst.
CSRCS ist in der config.mk angegeben.
Florian schrieb:> Das file ist nicht "zusammengeklaubt" ;) sondern von> ATMEL siehe post weiter oben..
Was es nicht wirklich besser macht. :-/
> CSRCS ist in der config.mk angegeben.
Hmm, naja, ich sehe keinen großen Sinn drin, sowas auf mehrere
Dateien aufzuteilen. Nachdem du das Makefile selbst ja nun auch
angefasst hast, kannst du die paar Makros auch gleich dort drin
pflegen. Ist aber Geschmackssache. Ich kann mich persönlich auch
mit diesen auto-dependencies nicht wirklich anfreunden. Ich würde
da lieber ein explizites "make depend" benutzen, das seine
Informationen am Ende des Makefile selbst pflegt.
U.R. Schmitt schrieb:> habt Ihr auch an die Abhängigkeiten der includierten .h Files gedacht
Ich hoffe ja, er includiert seine erzeugten auto-dependencies auch
irgendwo irgendwie.
ohne erfolg.
Wenn ich die object datein nicht
im output ordner,sondern in dem Ordner erstelle wo
die Quelldatein liegen.
(ist etwas unschön im Dateisystem aber ok)
Im Anhang ein Makefile, bei dem die erzeugten Dateien (o, elf, lst, map,
sym etc.) in einem getrennten Verzeichnis abgelegt werden. Änderungen in
Quellcodedateien werden automatisch berücksichtigt. Es gibt auch eine
Liste, in der man andere Dateien (z.B. .h oder das Makefile selbst)
eintragen kann, deren Änderungen ebenfalls ein rebuild auslösen. VPATH
wird nicht genutzt, es kommen GNU make Makros zur Anwendung, somit sehr
wahrscheinlich nicht mit anderen make-Programmen verwendbar. Im Anhang
sind ein paar projektspezifische Einstellungen und ist für arm-*-gcc
(nicht avr-gcc). Die Vorgehensweise sollte aber hoffentlich dennoch gut
ersichtlich sein. Der Fall, dass Quelldateien den gleichen Dateinamen
haben aber in unterschiedlichen Verzeichnissen abgelegt sind (z.B.
.../UART/lowlevel.c und .../SPI/lowlevel.c), wird nicht abgefangen.