Hallo,
vorab: Sollte es zu diesem Thema bereits irgendwo etwas geben was passt,
bitte gerne verlinken. Zumindest auf die Schnelle habe ich hier nichts
gefunden.
Was ich mir vorstelle:
Oft hat man sowohl in C als auch ASM das "Problem", dass man zum einen
wiederverwendbaren Code haben möchte, sich aber viele Sachen was die
Hardware betrifft zwischen verschiedenen Projekten variieren.
Beispiel:
Ich habe eine tolle PWM Ansteuerung in ASM geschrieben. In einem Projekt
hängen die LEDs an Port A/B, im anderen Projekt an Port B/C. Mal ist es
eine 4x4 Matrix, mal eine 8x8 Matrix etc.
Natürlich kann man jetzt hingehen und den Code so generisch
programmieren, das viele Sachen erst zur Laufzeit parametriert werden.
Aber das kostet wieder Zeit. Viel sinnvoller wäre es doch, die
"Rahmenbedingungen" per #define zur Übersetzungszeit anzugeben.
Und wie macht man DAS nun genau am besten?
Den Sourcecode "includen" finde ich unsauber, da auch dadurch jedesmal
alles eingebundenene mit neu übersetzt wird.
Kann ich (in Atmel Studio 6) den Sourcecode aus einem anderen
Verzeichnis ziehen, die Objektdatei aber im aktuellen Arbeitsverzeichnis
erstellen lassen?
Also z.B. für die Übersetzung folgende Struktur haben:
MyProject\main.c -> MyProject\main.o
Common\superpwm.c -> MyProject\superpwm.o
Wobei der Sourcecode in Common\superpwm.c ein #include
"superpwm_config.h" machen soll, aus dem er die Parametrierung (welche
Ports, Anzahl der LEDs etc.) zieht, und diese Includedatei soll
natürlich ebenfalls aus dem MyProjekt-Verzeichnis kommen.
Und dann alles zum fertigen elf/hex in MyProject verlinken.
Ich hoffe es ist klar geworden was ich erreichen möchte? Unter Linux
würde ich einfach im Projektverzeichnis einen (Soft-)Link auf den
gemeinsam zu nutzenden Sourcecode erstellen: superpwm.c ->
/home/bla/common/superpwm.c
Aber es ist ja nunmal Windows (XP), und da sind Links nicht ganz so
einfach zu machen.
Viele Grüße
Markus
adrock schrieb:> Viel sinnvoller wäre es doch, die> "Rahmenbedingungen" per #define zur Übersetzungszeit anzugeben.
Es ist keine schlechte Idee, möglichst viele Sachen von vornherein als
#define anzulegen. Bei günstiger Benennung der Makros kommentiert sich
später der Code von selbst.
adrock schrieb:> Aber es ist ja nunmal Windows (XP), und da sind Links nicht ganz so> einfach zu machen.
Warum nicht einfach in der Nähe der AVR-GCC-Standard-Lib deine eigene
codesammlung anlegen? An die kommt man dann per #include
<meinelib/lalala.h> genau so einfach ran.
Ich machs immer erstmal so, dass ich mir die Sachen, die ich woanders
schonmal funktionierend habe, einfach mit ins aktuelle
Projektverzeichnis mit rein ziehe und im makefile mit eintrage. Dass das
jetzt 200ms länger zum neu dazukompilieren braucht, stört mich nicht
weiter. Projekte werden nur im Ganzen archiviert. Wenn ich was an den
Schnipseln ändere, wird das im Projekt so verankert. Sonst müsste ich
moch eine eigene Versionskontrolle für meine Schnipsel aufmachen... Kann
ja sein, dass ein Schnipsel plötzlich nicht mehr abwärtskompatibel
ist...
Hat sich ein Codeschnipsel bewährt, kommen .c und .h Datei in einen
"Snippets" Ordner. Da ist dann alles thematisch und funktional geordnet
drin. Wenn an einem Snippet optimiert wurde und ich halte es für nötig,
das mit zu sichern, wird die Neuerung nicht nur im aktuellen Projekt
sondern auch im Snippets-Ordner eingepflegt.
mf mf
PS: In FAT32 kann man Hardlinks setzen bzw. "dazupfuschen". Das geht nur
solange gut, bis jemand den Datenbereich woanders hinschiebt oder
löscht. BUMM! Es gibt nämlich imho keinen Link-Count...
Hmmm...
ok, also das mit dem einfach include von "mylib/source.h" geht schonmal
schief, wenn man gemischt C und ASM Code in einem Projekt mischt - was
ich ab und zu mache (zeitkritische Sachen in ASM, den Rest in C).
Aber hey, das bringt mich auf eine Idee:
Ich mache in das Projekt einfach eine Art "stub" Datei. Also angenommen
ich habe in meiner Lib zwei tolle Sachen:
mylib\pwm\fastpwm.S
mylib\math\circle.c
Und möchte beide in meinem Projekt nutzen, dann mache ich
myproject\_fastpwm.S
Inhalt z.B.:
#define ROWPORT PORTA
#define COLPORT PORTB
#define NUMROW 4
#define NUMCOL 4
#include "mylib\fastpwm.S"
und
myproject\_circle.c
Inhalt dann einfach nur:
#include "mylib\circle.c"
So habe ich keine Links, verweise aber dennoch immer auf den aktuellen
Sourcecode in meiner Lib :-) Und die notwendigen Definitionen für die
Hardware habe ich auch gleich mit drin.
Grüße
Markus
PS: Sollte natürlich heissen:
#include "mylib\pwm\fastpwm.S"
und
#include "mylib\math\circle.c"
Aber ich glaube so kann man das gut handlen. Sogar die Abhängigkeiten
sollten hinhauen. So wird nicht unnütz immer das gleiche wieder
übersetzt, wenn garkeine Änderungen vorhanden sind.
Grüße
Markus
> Den Sourcecode "includen" finde ich unsauber, da auch dadurch jedesmal> alles eingebundenene mit neu übersetzt wird.
Das geht wg. "static inline" und C++ templates mittlerweile gar nicht
mehr anders. Das hat mit "unsauber" wenig zu tun, weil es der Compiler
so vorgibt.
> Kann ich (in Atmel Studio 6) den Sourcecode aus einem anderen> Verzeichnis ziehen, die Objektdatei aber im aktuellen Arbeitsverzeichnis> erstellen lassen?
Wie es im Studio aussieht, weiß ich nicht. Bei GNU makefiles ist es
VPATH.
Damit mache ich es prinzipiell so, wie Du skizziert hast.
> Unter Linux> würde ich einfach im Projektverzeichnis einen (Soft-)Link auf den> gemeinsam zu nutzenden Sourcecode erstellen: superpwm.c ->> /home/bla/common/superpwm.c
VPATH erledigt dies, das sollte dann auch unter Windows funktionieren.
Symlinks innerhalb von SW-Projekten, evtl. noch im Zusammenspiel mit
Versionskontrollsystemen ... kann gut gehen, muss aber nicht.
> Ich machs immer erstmal so, dass ich mir die Sachen, die ich woanders> schonmal funktionierend habe, einfach mit ins aktuelle> Projektverzeichnis mit rein ziehe und im makefile mit eintrage.
Und da ist nie ein Bug drin? Und es wird nie ergänzt?
> Wenn an einem Snippet optimiert wurde und ich halte es für nötig,> das mit zu sichern, wird die Neuerung nicht nur im aktuellen Projekt> sondern auch im Snippets-Ordner eingepflegt.
Wenn aber ein Bug gefunden wird, muss dies überall nachgezogen werden.
Refactoring macht auch keinen Spaß.
Der Vorteil mag darin liegen, dass eine neue oder geänderter Version
andere Projekte nicht betrifft. Es kann auch übersichtlicher sein.
Hatte ich tatsächlich früher auch so gemacht, aber die Wartung war ein
Graus. Inzwischen lebe ich damit, dass ein Querschläger irgendwo
auftritt, der Schmerz ist m. E. geringer.
adrock schrieb:> So habe ich keine Links, verweise aber dennoch immer auf den aktuellen> Sourcecode in meiner Lib :-) Und die notwendigen Definitionen für die> Hardware habe ich auch gleich mit drin.
Wie schon geschrieben, ich verwende VPATH. In den "common header files"
wird grundsätzlich ein "config.hpp" inkludiert - das kommt im Prinzip
vom Projekt. Damit sparst Du Dir die doppelten Dateien.
> Aber ich glaube so kann man das gut handlen. Sogar die Abhängigkeiten> sollten hinhauen. So wird nicht unnütz immer das gleiche wieder> übersetzt, wenn garkeine Änderungen vorhanden sind.
Das macht er auch nicht. Via VPATH werden die common-Geschichten
virtuell eingebunden. Den Rest erledigt das Makefile ganz normal via
Abhängigkeiten.