Guten Tag,
ich suche schon eine Weile nach einer vernünftigen Lösung für folgendes
Problem und hatte leider hier oder bei Google nichts gefunden :(
Ich habe ein Projekt, welches für verschiedene
Kommunikationsschnittstellen und für verschiedene Übertragungsformate
(Binärframe/ASCII) genutzt werden soll. Also ein Projekt für
verschiedene Ergebnisse.
Dazu hatte ich geplannt 4 Bibliotheken anzulegen (Uart, SPI, Ascii,
Binär) und diese dann abhängig von einem #define einzubinden. Für die
Headerdateien ist dies auch kein Problem, für das Objektfile (.a) habe
ich jedoch keine Ahnung, ob bzw. wie sich dieses abhängig von einem
define Einbinden lässt.
Gibt es dafür eine Lösung oder ein generell anderes Herangehen an das
geschilderte Problem?
Grüße
Martin
MartinK schrieb:> für das Objektfile (.a) habe> ich jedoch keine Ahnung, ob bzw. wie sich dieses abhängig von einem> define Einbinden lässt.
Nein, das geht nicht. Kanns Du höchsten über ein Makefile machen. Ist
aber eigentlich überflüssig. Du kannst einfach alle Bibliotheken
dazulinken, der Linker ist schlau genug nur die Teile zu nehmen, die
tatsächlich gebraucht werden.
Mein Gedanke war die selbe Funktion verschieden zu implementieren, also
z.b: SendData(u8* Data, u8 Len), selche dann mit SPI anders
implementiert ist als mit Uart. Aber ich muss wohl getrennte
Bibliotheken machen, jeweils unterschiedliche Namen geben (UartSendData,
SpiSendData) und dann per Makro zuweisen. Ist das praktikabel oder ein
Problem?
Also z.B.
#if USE_SPI
#define SendData(Data,Len) SpiSendData(Data,Len)
#endif
#if USE_UART
#define SendData(Data,Len) UartSendData(Data,Len)
#endif
den könnte ich dann ja als Header einbinden.
Danke für die Anregung alle zu Linken und auswählen zu lassen.
Du kannst im make-file auch verschiedene Targets angeben.
Und dann mit make SPI entsprechen compilieren
Im Zweifelsfall gibst du dem Compiler noch mit -DUSE_SPI hilfe.
... schrieb:> Nein, das geht nicht. Kanns Du höchsten über ein Makefile machen. Ist> aber eigentlich überflüssig. Du kannst einfach alle Bibliotheken> dazulinken, der Linker ist schlau genug nur die Teile zu nehmen, die> tatsächlich gebraucht werden.
und was ist mit Globalen Variablen?
MartinK schrieb:> #if USE_SPI> #define SendData(Data,Len) SpiSendData(Data,Len)> #endif
Ich würde statt dessen ein SendData() als static inline im Header
definieren, das nur SpiSendData() mit den selben Argumenten aufruft.
Dann kennt der Compiler SendData() als Funktion und kann Fehlermeldungen
passender anzeigen. Wenn Optimierungen eingeschaltet sind, ist der
erzeugte Code identisch zu dem mit Defines.
Peter II schrieb:> und was ist mit Globalen Variablen?
Die .a Dateien, die von den GNU Tools als statische Libraries verwendet
werden, sind einfach mit ar zusammengepackte Objektdateien. Wenn ld ein
solches Archiv einbinden soll, nimmt er daraus nur die Objektdateien,
die eine bisher unaufgelöste Referenz als Symbol anbieten (deshalb ist
auch die Reihenfolge wichtig). Damit kommt auch der Rest dieser
Objektdatei rein.
Oder war die Frage anders gemeint?
MartinK schrieb:> Mein Gedanke war die selbe Funktion verschieden zu implementieren, also> z.b: SendData(u8* Data, u8 Len), selche dann mit SPI anders> implementiert ist als mit Uart. Aber ich muss wohl getrennte> Bibliotheken machen, jeweils unterschiedliche Namen geben (UartSendData,> SpiSendData) und dann per Makro zuweisen. Ist das praktikabel oder ein> Problem?> Also z.B.>> #if USE_SPI> #define SendData(Data,Len) SpiSendData(Data,Len)> #endif> #if USE_UART> #define SendData(Data,Len) UartSendData(Data,Len)> #endif>> den könnte ich dann ja als Header einbinden.> Danke für die Anregung alle zu Linken und auswählen zu lassen.
Wozu denn diese Verunstaltung mit Makros? Wenn du eh Bibliotheken
machst:
- Es gibt Bibliotheken wie libuart, libspi, libusb, ...
- Alle implementieren die benötigten Interfaces SandData et.al.
jeweils auf ihre Weise.
- Die Interfaces werden in einem Header bekannt gemacht, zB:
1
extern void SendData (const void*, size_t);
- Es wird die Bibliothek hinzugelinkt, welche die Interfaces auf die
gewünschte Art implementiert. Soll eine UART-Kommunikation
stattfinden, gibt's einfach ein -luart bei den Linkeroptionen.
Genau da liegt ja das Problem (siehe Titel): Ich möchte die gelinkten
Bibliotheken nicht jedes mal händisch ändern, sondern per #define
USE_UART 1 einbinden bzw. #define USE_UART 0 entfernen. Nun war der
Vorschlag ja einfach alle Libraries zu linken und nur jene Funktionen zu
nutzen, die passen. Das gerade sollen die Makros ermöglichen.
MartinK schrieb:> sondern per #define> USE_UART 1 einbinden bzw. #define USE_UART 0 entfernen.
Wie schon geschrieben: Mach das alles im Makefile.
Da kannst so sowohl die Defines ändern (-DUSE_UART in die C-Flags) als
auch die Bibliotheken auswählen (-luart in die LD-Flags).
Machen 10000 andere Projekte auch so, nur das da meist noch ein autoconf
o.Ä. vorgeschaltet ist, um auch noch das Makefile-parametrieren zu
automatisieren.