Hallo,
ich weiss nicht ob das so richtig hier her passt, aber ich finde keinen
besseren Platz.
Kurz zu dem/die Projekten. Ich brauche da ein paar Tipps wie man das mit
Make lösen kann.
Es handelt sich um ein Projekt das bisher aus 3 ATmegas, mit
unterschiedlichem Takt, besteht.
Kurz zur groben bisherigen File Struktur
source/global_files/
source/tx_main/bootloader
source/tx_main/main
source/tx_main/lcd
source/rx_main/bootloader
source/rx_main/main
source/pc/
unter global Files liegen bisher Include Files die in allen anderen
referenziert werden mit defines, structs etc.
Hier sollen nun auch "c" Files hin mit Routinen die überall gleich sind.
Da zum Teil die ATmegas unterschiedlich sind und die Taktfrequenz, fällt
eine lib weg.
Nun dachte ich, ich kann die "c" File im make das z.B. in
"source/tx_main/main" liegt relativ einbinden in der Art:
"../../global_files" so wie bei den Includes. Das geht leider nicht.
Hier kommt eine Fehlermeldung das das Object File nicht erzeugt werden
konnte, da dass object Directory fehlt (müsste ich genau nochmal
ausprobieren wenn notwendig).
Wie löst man so etwas ? Das wird doch bestimmt in vielen Projekten
benötigt.
Rekursive makes ?
Wie gebe ich dann Parameter wie CPU und FCPU weiter ?
Wäre es dann ein make das alle "Projekt Teile" auf einmal erstellt ?
Falls wichtig, ich entwickle unter Linux und das Projekt liegt unter SVN
Kontrolle. Von "Soft" links würde ich gerne Abstand nehmen.
Für Tipps bin ich dankbar
Juergen
In meinen — allerdings nur privaten — Projekten habe ich mir dazu ein
kleines Quell-Repository angelegt, weil wie gesagt Libs ausscheiden
wegen mangelnder Skalierbarkeit (SFRs, Defines, F_CPU, Port-Definitionen
im Projekt, etc).
Im Makefile gebe ich dann die Quellen an, die aus dem Repository
stammen:
SRC sind die "normalen" Quellen, die Compiliert/Assembliert werden und
COMMON_SRC die sachen aus dem Repository.
D.h. die Quellen aus dem Repository werden einmal ins Projektverzeichnis
kopiert und bleiben dann dort und können dann dort auch überschrieben
werden (bei lokalen Änderungen ist es sinnvoll sie aus COMMON_SRC zu
entfernen).
Ansonsten wird bei einer Änderung im Repository die Arbeitskopie
überschrieben.
Anstatt zu kopieren, kann man natürlich auch aus SVN oder git
auschecken; für meine Bastlprojekte führe ich kein VCS.
Dieser Ansatz ist dann praktikabel, wenn die Quellen im Quell-Repository
hinreichend stabil und allgemein genug sind, um nicht doch für jedes
Projekt wieder Anpassungen machenzu müssen.
Dazu gehören zB UART-Implementierungen, die zwar noch vom aktuellen µC
anhängen per -mmcu oder avr/io.h, aber sonst keine Änderungen mehr
benötigen ausser zB per Makro ob man eine Poll-Version mächte oder eine
gepufferte, Interrupt-getriebene Verson. Anderer typischer Use-Case sind
Makros für die Port-Zugriffe wie SET(PORT_LED), MAKE_IN(PORT_LED),
MAKE_OUT(PORT_LED), TOGGLE(PORT_LED), etc.
Daneben gibt es bestimmt auch viele andere, professionellere Ansätze ;-)
Aber für meine Projekte tut's das schon seit langem und es ist einfach,
ein neues Projekt zusammenzustöpseln.
Jürgen Sachs schrieb:> Wie löst man so etwas ? Das wird doch bestimmt in vielen Projekten> benötigt.> Rekursive makes ?
Ob Du es rekursives Make nennst oder nicht, aber das Aufteilen in je ein
Makefile für jedes zu erzeugende Programm ist sicher sinnvoll. Die
einzelnen Makes werden dann kleiner und übersichtlicher.
Ein übergeordnetes Makefile ruft dann diese 3 makes auf.
Du musst eben auch beachten, dass die komplierten Objects für die
gemeinsam benutzten Quellen in separate Verzeichnisse müssen, weil sie
für unterschiedliche Prozessoren kompiliert werden müssen.
Ich würde zusätzliche Verzeichnisse anlegen
implement/tx_main
implement/rx_main
implement/pc
und in diesen macht je ein makefile aus den relativ referenzierbaren
Quellen das jeweilige Programm.
Damit die Quellen gefunden werden musst Du entweder eine eigen Regel
schreiben, z.B.
%.o : ../source/global_files/%.c
$(CC) ...
mit der man aus .c files in ../source/global_files ein gleichnamiges obj
im aktuellen Verzeichnis erzeugst, oder du arbeitest mit VPATH, damit
kann man auch den Ort von Quellen angeben.
> Wie gebe ich dann Parameter wie CPU und FCPU weiter ?
Über die Parameter für das make
make CPU=$(CPU) FCPU=$(FCPU)
> Wäre es dann ein make das alle "Projekt Teile" auf einmal erstellt ?
Ja, siehe oben
Hi, Jürgen,
> Es handelt sich um ein Projekt das bisher aus 3 ATmegas, mit> unterschiedlichem Takt, besteht.
Verstanden.
Aber wo habe ich überlesen, wie die Konfiguration nun aussehen soll?
Vielleicht ein Atmega, der die drei bisherigen Programme enthält, der
in jede der bisherigen drei Fassungen gesetzt werden kann und dann
anhand eines Merkmals erkennt, wo er sitzt und welches Programm
abzuarbeiten hat?
Oder soll das beim Kompilieren geschehen?
Ansonsten - ich habe mit GCC schon .c-Dateien aus anderen Directories
eingebunden. Aber die main.c, bzw. die mit dem Namen des Programms,
befand sich dabei immer in dem Directory, in dem ich dann auch
kompiliert habe.
Ciao
Wolfgang Horn
jeder Teil
- tx_main
-rx_main
-tx_lcd
benutzt einen eigenen Prozessor, der vom Typ her aber fest steht.
also tx_main hat einen bootloader und den "main" part der auf einem
atmega32 mit 16MHz läuft.
Analog für die rx_main (m32@16MHz) und tx_lcd (m16@8MHz).
Diese benutzen teile aus global Files (I2C, Uart, Umwandelung Routinen)
Es ist auch ausreichend immer nur ein Projekt zu erstellen
Gruss
Juergen
Danke, Jsachs,
jetzt sehe ich klar.
Aber ich bekenne auch - den prozessorspezifischen Bootloader habe ich
immer getrennt von der Application entwickelt.
Defines und Teile der Sourcen waren identisch.
Die Fertigung hat dann mit Boundary Scan beides geflasht.
Ciao
Wolfgang Horn
Jürgen Sachs schrieb:> Hier kommt eine Fehlermeldung das das Object File nicht erzeugt werden> konnte, da dass object Directory fehlt (müsste ich genau nochmal> ausprobieren wenn notwendig).
Genaue Fehlermeldung wäre sicherlich hilfreich.
Auf jeden Fall sollte sowas mit expliziten Regeln zum Compilieren
gehen, weil man dabei die Quell- und Ausgabedatei separat festlegen
kann:
1
COMMON_SRC = ../../common
2
3
...
4
5
foo.o: $(COMMON_SRC)/foo.c
6
$(CC) $(CFLAGS) -c -o foo.o $(COMMON_SRC)/foo.c
Mit Suffixregeln gibt es keinen generischen Ansatz, wobei GNU make,
wie ich den üblichen "creeping featurism" kenne, dafür sicher irgend-
einen Hack, ähm, Hook bietet. ;)
Jörg Wunsch schrieb:> Jürgen Sachs schrieb:>> Hier kommt eine Fehlermeldung das das Object File nicht erzeugt werden>> konnte, da dass object Directory fehlt (müsste ich genau nochmal>> ausprobieren wenn notwendig).>> Genaue Fehlermeldung wäre sicherlich hilfreich.
Warum der Fehler kommt ist mir klar, weil als Ursprung das "obj"
genommen wird und nicht "."
> Auf jeden Fall sollte sowas mit expliziten Regeln zum Compilieren> gehen, weil man dabei die Quell- und Ausgabedatei separat festlegen> kann:>>
1
> COMMON_SRC = ../../common
2
>
3
> ...
4
>
5
> foo.o: $(COMMON_SRC)/foo.c
6
> $(CC) $(CFLAGS) -c -o foo.o $(COMMON_SRC)/foo.c
7
>
>> Mit Suffixregeln gibt es keinen generischen Ansatz, wobei GNU make,> wie ich den üblichen "creeping featurism" kenne, dafür sicher irgend-> einen Hack, ähm, Hook bietet. ;)
Verstehe ich das richtig, das ich das nicht mit
%o: $COMMON_SRC ....
Also eine Regel für alle Files machen kann...
Dann muss ich mir make nochmals genau ansehen. Und mach das durch
"Rekursive".
Ich hab nur noch kein HowTo für make gefunden, das ich verstehe :-(
Gibt es kein "Auto make" das nur die "c" files bekommt und den rest
Automatisch festlegt ?
Gruss
Juergen
Jürgen Sachs schrieb:> Verstehe ich das richtig, das ich das nicht mit> %o: $COMMON_SRC ....> Also eine Regel für alle Files machen kann...
Jein.
Solche Regeln nennt man static pattern rules.
Du brauchst aber 2 Regeln, weil Du 2 "Arten" von obj-files hast: die von
common und die vom Projekt.
OBJ_COMMON := c1.o c2.o
OBJ_PROJECT := p1.o p2.o
#rule 1, gilt für c-files aus common
$(OBJ_COMMON) : %.o : $(COMMON_SRC)/%.c
$(CC) .....
#rule 2, gilt für c-files aus lokalem directory
$(OBJ_PROJECT) : %.o : %.c #rule 2,
$(CC) .....
Jürgen Sachs schrieb:> Gibt es kein "Auto make" das nur die "c" files bekommt und den rest> Automatisch festlegt ?
Weiss nicht. Wäre zu einfach und wo bleibt dann der Spass :-)
automake gibt es natürlich, und möglicherweise könnte es das auch
können, was du da willst — aber ob du dich darin erst einarbeiten
magst, wage ich zu bezweifeln. ;-)