Nur geänderte datein compilieren

Gast #1824801
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
#1824828
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.
Gast #1827699
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.
Angehängte Dateien:
#1827776
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)
Gast #1827881
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.
Moderator Persönliche Seite #1828230
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.
#1828248
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.
Moderator Persönliche Seite #1828320
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.
#1828327
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 :-)
Moderator Persönliche Seite #1828407
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.
#1828476
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.
Moderator Persönliche Seite #1828484
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.
Gast #1828512
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.
Moderator Persönliche Seite #1828519
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.
Gast #1829467
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.
Moderator Persönliche Seite #1829649
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.
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren