Hallo Leute,
mein make will nicht so wie ich. Ich möchte gern die Abhängigkeiten
meiner c Quelltexte von den Headern automatisch ermitteln. Im Netz habe
ich leider keine vollständige Anleitung und kein Beispiel gefunden, ist
wahrscheinlich zu einfach...
Also jetzt von Anfang an:
Man kann make eine Regel angeben wie aus *.c *.o dateien gemacht werden:
1
%.o:%.c
2
$(COMPILE) -c $< -o $@
Leider ist es hier nicht möglich die Abhängigkeiten von den *.h
anzugeben - kann ja auch nicht sein, sie wären ja für alle *.c gleich.
Die GNU Compiler haben deswegen die Option -MM welche die Abhängigkeiten
der *.c Dateien ausgibt. Mann soll laut Internet dies machen:
1
depend:
2
$(COMPILE) -MM $(CSOURCES) >.depend
3
4
-include .depend
Das findet man im Netz aber keine weiteren Anweisungen, was mich
vermuten lässt, man schreibt es einfach mit ins Makefile, was ich auch
tat.
Die Abhängigkeiten werden vom avr-gcc in die Datei .depend geschrieben
und ins Makefile eingebunden. In der Datei steht so etwas:
1.)touch typen.h. Davon sind alle drei c Dateien abhängig.
2.)make. Es sollte jetzt alles übersetzt werden - wird es aber nicht.
Was mache ich falsch?
Hier noch das Makefile:
Danke Johann L.! Ja, genau so ein dummer Fehler muss das sein. Aber ich
habs noch nicht ganz geschnallt. Wie funktioniert make eigentlich?
Ich stelle mir das so vor: make will all herstellen dafür braucht es
main.hex dafür main.bin und dafür $(OBJECTS) mit diesen Objects sucht
das make die Zeile %.o: %.c und stellt die Objects wie dort angegeben
her, wenn sie denn nicht aktuell sind.
In $(OBJECTS) sollten die drei Objekte stehen, stehen sie ja auch
1
main.bin: $(OBJECTS)
2
$(COMPILE) -o main.bin $(OBJECTS)
dies ist für die zweite Ausgabezeile des Compilers (eigentlich Linkers)
verantwortlich und da sind sie aufgeführt.
Das Makefile macht folgendes: Es schaut in alle SOURCES und sucht die
#includes. Gibt es das includierte .h in meinem Libverzeichnis als .c
wird dieses .c über NEEDETLIBS zusammen mit SOURCES in die CSOURCES und
OBJECTS aufgenommen und sollen mit übersetzt werden.
Wenn ich eine meiner Klassen in einem Programm includiere such das make
sich automatisch die Quelltexte und bindet sie ein.
Das ist ja ein Ding, da hast Du recht. Irgendwie bin ich jetzt ganz
verwirrt, wiso funktioniert das eigentlich sonst immer? Aber ich sehe
das genauso wie Du. Nur die Reaktion passt nicht so ganz, wenn das Ziel
nicht existiert, wegen das falschen Pfades, müsste das make den Compiler
immer anwerfen, auch wenn das richtige Ziel schon aktuell ist.
Oder wie, oder was? ich bin wirklich etwas verwirrt aber teste das
nachher mal.
Danke auf jeden Fall.
hannes schrieb:> Nur die Reaktion passt nicht so ganz, wenn das Ziel> nicht existiert, wegen das falschen Pfades, müsste das make den Compiler> immer anwerfen, auch wenn das richtige Ziel schon aktuell ist.
Nein, denn das falsche Ziel kommt ja nie zum Zuge.
Wenn nirgendwo sonst im Abhängigkeiten-Baum ein digital.o benötigt wird,
dann versucht Make auch nicht eines zu erstellen, und interessiert sich
damit auch nicht die Bohne dafür für dessen Abhängigkeiten.
Na das erklärt einiges, nicht nur das beschriebene Problem. Ich habe
jetzt händisch die Pfade nachgetragen und siehe da, es macht was es
soll. Vielen Dank Stefan!
Die Abhängigkeitsdatei stammt vom Compiler. Kann man den überreden das
er gleich den Pfad mit hinschreibt? Oder gibt es eine andere Lösung?
Vielleicht noch als Anregung:
Bei komplexeren Projekten ist es nicht unüblich, je Verzeichnis ein
Makefile vorzusehen.
Das "Master-Makefile" enthält dann je Verzeichnis einen Targeteintrag,
dessen buid rule in etwa so aussieht:
1
cd $verzeichnis ; make $mastertarget ; cd ..
$mastertarget ist entweder ein Pseudo-Target wie "all" oder "clean" oder
eine "echte" Target-Datei.
Grüße
Stefan
Bei mir geht es im Grunde um eine Library, die ich als Quellcode halte
weil ich Probleme bei einem Prozessorwechsel befürchte. Im
Verzeichnisbaum wird die Lib dann immer über oder neben dem
Projektverzeichnis stehen.
Ich habe den Verdacht, dass ich etwas denke, was man so nicht denkt und
der Compiler deswegen, aus meiner Sicht, komische Dinge tut:
Der Compileraufruf ist für die Erzeugung der Abhängigkeiten und der
Objekte identisch, bis auf das -MM natürlich. Der Compiler wird mit dem
Pfad zum Quellcode aufgerufen und er legt das Objekt in dem selben Pfad
ab. Soweit Logisch. Erzeugt er dagegen Abhängigkeiten, löscht er den
Pfad zum Objekt (finde ich komisch) - aber nicht zu den .h - das ist mir
gänzlich unverständlich, weil nichtmal konsistent.
Hannes schrieb:> Der Compileraufruf ist für die Erzeugung der Abhängigkeiten und der> Objekte identisch, bis auf das -MM natürlich.
Nein, ist er nicht. Das -o in der Regel für den Compilerlauf bestimmt
den Namen (einschließlich Pfad) des Ziel der Kompilierung. Beim
depend-Target gibt es diese Spezifikation nicht. Der Compiler leitet den
Zielnamen einfach von der Quelldatei ab - und nimmt die einfachste
Variante.
Um Schock *Horror* mal aus der Dokumentation zu zitieren wie er dies
macht - ja, lesen bildet :-)
> Unless specified explicitly (with -MT or -MQ), the object file name> consists of the name of the source file with any suffix replaced with> object file suffix and with any leading directory parts removed.
"with any leading directory parts removed". Ist doch eindeutig.
Die Lösung ist in der Dokumentation auch angedeutet "Unless specified
explicitly (with -MT or -MQ)". Angedeutet, weil man sich mit den
Make-Stringfunktionen und eingebauten Variablen das richtige Argument
basteln muss.
Huh, da hast Du aber deutliche Worte gefunden Malte.
Aber beschäftigen wir uns zunächst mit dem Vergleich unserer Personen:
1. Du kannst mir etwas erklären. (stimmt wahrscheinlich, habe mich mit
deiner Antwort noch nicht tiefer beschäftigt.) Punkt für dich.
2. Du kannst lesen und bist gebildet. Eindeutig Punkt für dich.
3. Du kannst Englisch. Punkt für dich.
4. Du weist was eindeutig ist - na, Doppelpunkt für dich - nein, die
Eindeutigkeit wurde ja nochmals wiederholt ohne sie zu übersetzen oder
gar den Sinn in eigenen Worten wiederzugeben. Das ist ja Doppel doppel
also vier Punkte.
Das sind also 0 Punkte für mich und 6 Punkte für dich. Du darfst mich
Wurm nennen.
:-) (Wenn ich die richtige Antwort kriege sage ich warum ich grinse)
--------------------------------------------
Ich hatte ein paar Jahre Auszeit vom AVR und von diesem Forum, nun habe
ich beides wiederendeckt und es macht mir Spaß. Aber ich hatte bald den
Eindruck das der Ton hier im Forum rauer geworden ist, was dem Spaß
abträglich ist.
Das ist doch unsere Sandkiste, wenn wir uns die Schäufelchen um die
Ohren hauen wird die Sandkiste bald leer sein oder die Insassen
vergreisen, weil keine neuen Leute mehr kommen. Ich selbst bin
wankelmütig ob ich bleiben soll, denn ich bin zum Spaß hier und es gibt
hier viele nette und kompetente Leute mit denen es wirklich Spaß macht.
Aber soll ich hier ein Projekt vorstellen um mich somit dem rauen Wind
auszusetzen? Ich warte noch ab. Bitte macht dieses Forum nicht kaputt
indem die Leute runtergeputzt werden.
Bringt ja auch nichts, wenn hier nur Idioten sind warum seid ihr hier?
Wenn man zu dem Schwachsinn nichts mehr sagen kann, warum dann
Antworten? Solche Punktespiele von oben funktionieren nicht, weil ein
Leser das Punktesystem so nicht aufstellt. Richtig viele Punkte bekommt
man für gute Erklärungen, richtig Kompetent ist der, der einen
Sachverhalt so erklären kann das jeder Depp das versteht. Das merkt auch
der Leser und gibt richtig Punkte.
Und mal ganz ehrlich, worum geht es hier überhaupt? Ich fand meine Frage
spannend, sie betrifft aber nur mein Hobby ist also nicht lebenswichtig.
Die Lösung, ja mal sehen, wenn sie interessant ist werde ich die
verwenden, wenn nicht - wie lange braucht ein GHz Prozessor im
schlechtesten Fall um 8 kB Code zu erzeugen? Im Zweifel ist sogar das
make überflüssig. Es geht doch um nichts wichtiges, da können wir auch
nett zueinander sein.
Das hab ich geschrieben weil mir dieses Forum am Herzen liegt und ich
hoffe das, dass Klima wieder besser wird. Ich tauche dann erstmal wieder
ab.
Hannes
Stefan Wagner schrieb:> Bei komplexeren Projekten ist es nicht unüblich, je Verzeichnis ein> Makefile vorzusehen.
"recursive make considered harmful".
Just say "no".
Liegt es evtl. einfach daran, dass die .depend-Datei nicht die korrekte
Endung *.obj sondern *.o enthaelt. Der g++ ist sich selbst nicht sicher,
ob er *.obj oder *.o erzeugt, wie es scheint :-(
Das sehe ich bei mir nämlich auch gerade.
schnelle (vllt. nicht perfekte) Lösung:
sed "s/.o: /.obj: /g" .depend > x
mv x .depend