Forum: Compiler & IDEs Nur geänderte datein compilieren


von Florian (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von ... (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

... 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.

von Florian (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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)

von Rolf Magnus (Gast)


Lesenswert?

Das klingt plausibel.
1
%.o: %.c
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:
1
 $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $(OUTPUT)/$(@F)

Also wird das .o-File in $(OUTPUT) erzeugt und beim nächsten Compilieren 
dann natürlich nicht im übergeordneten Verzeichnis gefunden.

von Florian (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

Vielleicht gibts auch hier
1
# Create objects files list with sources files
2
OBJECTS  = $(CSRCS:.c=.o) $(ASSRCS:.s=.o)
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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Vielleicht gibts auch hier
>
>
1
> # Create objects files list with sources files
2
> OBJECTS  = $(CSRCS:.c=.o) $(ASSRCS:.s=.o)
3
> 
4
>
> 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.

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:
> Karl heinz Buchegger schrieb:
>> Vielleicht gibts auch hier
>>
>>
1
>> # Create objects files list with sources files
2
>> OBJECTS  = $(CSRCS:.c=.o) $(ASSRCS:.s=.o)
3
>>
4
>>
>> 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 :-)

von Volker Z. (vza)


Lesenswert?

Wie wäre es damit. Geht auch mit algemeinen Regeln.
1
VPATH = objdir

http://www.gnu.org/software/make/manual/html_node/General-Search.html#General-Search

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Volker Zabe schrieb:
> Wie wäre es damit. Geht auch mit algemeinen Regeln.
>
>
1
> VPATH = objdir
2
>

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.

von Volker Z. (vza)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Florian (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von U.R. Schmitt (Gast)


Lesenswert?

Nur mal so ein kleiner Gedankengang:
 habt Ihr auch an die Abhängigkeiten der includierten .h Files gedacht 
:-))

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Florian (Gast)


Lesenswert?

Ich hab jetzt noch ein paar sachen versucht

http://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options
-L und -B option in
1
INCLUDES = -B"$(OUTPUT)" ...
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)
1
@echo '$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $(OUTPUT)/$(@F) 2> errors.txt' >> CheckErrors.bat
in
1
@echo '$(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@ 2> errors.txt' >> CheckErrors.bat

und die Zeile zum Linken anpasse
1
@$(CC) $(LDFLAGS) $(addprefix $(OUTPUT)/,$(notdir $(OBJECTS))) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
neu
1
@$(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

klappt es!
Danke für die Hilfe.

von Martin T. (mthomas) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.