Hallo Simon,
normal ist folgendes:
Zusammengehöriger Programmcode kommt in eine C-Datei, Symbole, die nach Außen hin sichtbar sein sollen, kommen in einen C-Header, der die
Definitionen Deklarationen enthält; Beispiel:
lcd.c:
static _lcd_write_byte(...);
void lcd_init(uint8_t arg)
{
...
}
lcd.h:
extern void lcd_init(uint8_t arg);
Den Namen des Argument kann man weglassen, es ist aber empfehlenswert, ihn anzugeben!
Alle Programmteile, die auf die Funktionen in lcd.c zugreifen möchten, binden nur den Header lcd.h ein, mehr nicht. C-Dateien, also Programmcode, bindet man niemals per include ein, auch wenn das häufig gemacht wird.
So, der nächste Schritt ist dann, dass aus allen C-Dateien Objektkode erzeugt wird, man erhält also zusätzlich eine lcd.o, die den ausführbaren Code aus lcd.c enthält. Man hat nun einen Haufen Objektdateien, die am Ende alle verlinkt werden, z.B. so:
avr-gcc $(OPT) -o main lcd.o main.o uart.o
So, was passiert aber, wenn sowohl lcd.c als auch main.c Funktionen aus der uart.c verwenden? Genau, beide binden den Header lcd.h ein. Dabei kann es aber dazu kommen, dass dieser Header wiederum andere Header einbindet, und dabei Header doppelt eingebunden werden.
Man behilft sich nun folgendermaßen:
Man prüft in jedem eigenen Header, ob ein bestimmtes Symbol (Präprozessorsymbol!) definiert ist, wenn ja, macht man einfach nichts, wenn nein, definiert man dieses Symbol und dann folgt der Headerinhalt. Beim nächsten Einbinden würde dann alles ignoriert werden.
Die gesamte C-Std macht das so und es wird auch so empfohlen; Beispiel:
Header uart.h
#if !defined(UART_H)
#define UART_H
#include <inttypes.h>
extern void uart_init(uint16_t bps);
extern void uart_putc(uint8_t ch);
...
#endif
Ende Header uart.h
Das war es schon
Im Makefile muss dann für jede Objektdatei ein Eintrag, z.B. für lcd.c:
lcd.o: lcd.c
<TAB> avr-gcc $(OPT) -c -o lcd.o lcd.c
-c gibt an, dass nur assembliert wird, kein Linken.
main.out: main.o lcd.o uart.o ...
<TAB> avr-gcc $(OPT) -o main.out main.o lcd.o uart.o
Je nach Projekt schleppt man auch mal fünf, 30 oder 200 Objektdateien herum und so nutzt man bestimmte Make-Regeln, wie folgende:
OBJ=lcd.o uart.o main.o vfd.o std.o
%.o: %c
<TAB> avr-gcc $(OPT) -o $@ $<
sprich: jede .o-Datei hängt von einer .c-Datei ab (Regel) und sie werden wie in der nächsten Zeile angegeben erzeugt, wobei $@ die Ausgabedatei ist (wird von make ersetzt) und $< der Platzhalter für die Eingabedatei ist.
Am Ende noch die Regel zum Erzeugen des Programms:
main.out: $(OBJ) # sprich: main.out hängt von allen angegeben Objektdateien ab
<TAB> avr-gcc $(OPT) -o main.out $(OBJ)
So kann ein Makefile mit dreieinhalb Zeilen riesige Projekte erzeugen (wobei das meist nicht reicht, aber theoretisch schon!)
P.S.: nur so kurz zusammengefasst - komme grad von einer Klausur wieder und wollte eigentlich ins Bett
_________________
[ Diese Nachricht wurde geändert von: DonComi am 15 Mär 2011 20:13 ]