Forum: Compiler & IDEs Problem beim erstellen und verwenden einer AVR Static Library


von Christian (Gast)


Lesenswert?

Hallo alle zusammen,

ich versuche zur Zeit eine eigene AVR Library zu erstellen. Das Problem 
dabei ist das der Linker die xxx.a scheinbar findet, sie aber nicht 
nutzt. Die darin enthaltenen Header können nämlich nicht im Projekt 
gefunden werden "no such file directory".

Vor weg, in dem Projekt wo ich die Library verwenden will, gebe ich dem 
Linker den Speicherort und den Namen der Archivdatei.

Anfangs habe ich das ganze auf einem Laptop mit 32 Bit Win7 und 32 Bit 
Eclipse mit AVR Plugin versucht, in der library eine Kleine Test 
Funktion mit zwei Zeilen erstellt und sie dann in einem anderen Projekt 
dem Linker bekannt gemacht, sie includiert und es lief. Konnte diese 
kleine Testfunktion also aufrufen und verwenden etc.

Das gleiche habe ich dann an meinem Rechner mit 64 Bit Win7 und 64 Bit 
Eclipse mit AVR Plugin versucht. Da ging es dann nicht, obwohl ich beim 
erstellen genau so vorgegangen bin.

Auch das nutzen der am Laptop erstellten library ging nicht.

Also bin ich zum Testen wieder zurück zur 32 Bit Version und habe dort 
mal eine etwas umfangreichere Libary erstellt (zum testen habe ich die 
xxx.c und xxx.h einfach in die anfangs erstellte Library gespeichert und 
erstellen lassen). Das interessante ist, das dass 32 Bit Eclipse nun 
keine der Header mehr erkennt (was vorher ja der Fall war), klicke ich 
aber auf die include Zeile(zum anzeigen der Datei), springt er in die 
Header der library.

Was mache ich falsch und hängt es vielleicht mit der 32/64 Bit 
Geschichte zusammen?

Mir ist übrigens aufgefallen das meine xxx.o Dateien im Archivfile leer 
sind...


Vielen Dank im voraus.

Christian

von Dr. Sommer (Gast)


Lesenswert?

Christian schrieb:
> Die darin enthaltenen Header können nämlich nicht im Projekt
> gefunden werden "no such file directory".
In static libraries sind keine header enthalten. Die Header muss man 
seperat mit kopieren und includepfade per -I angeben. Mit "avr-ar t 
xxx.a" kannst du dir den Inhalt der .a anzeigen lassen - da sind keine 
Header, nur .o files.

von Christian (Gast)


Lesenswert?

Aha, danke schon mal Dr. Sommer.

Dann verstehe ich den Sinn einer Static Libary vielleicht nicht so ganz. 
Sind dann in dem Static Library Projekt gar keine xxx.h drin, oder 
braucht der Archiver die zwar zum erstellen der xxx.a und ich muss sie 
dann in dem Projekt wo ich sie verwende einfach nochmal zusätzlich "-I" 
angeben?

So das ich zusammenfassend:

im Linker den Ort und Namen der xxx.a  (-l -L) und im Compiler die 
Header separat angebe (-I) ?


Wie realisiert man so was richtig in Eclipse? Wenn ich das Static 
Library Projekt erstelle, sind dann .c und .h in dem Projektordner im 
Workspace oder muss ich die Header irgendwie anders Separieren?

Wenn ich mir die Libarys im WinAVR anschaue sind .o .a und .h wirklich 
durch Ordner getrennt...

von Oliver (Gast)


Lesenswert?

Eine lib (xxx.a) enthält compilierten c-code.

Um diesen in einem C-Programm nutzen zu können, muß man die darin 
enthaltenen Funktionen und sonstiges dem Compiler bekannt machen, 
genauso, wie man das bei der Aufteilung auf mehrere Sourcedateien auch 
machen muß.

Das macht man üblicherweise in header-Dateien.

Oliver

von Christian (Gast)


Lesenswert?

Ah okay danke, das bedeutet dann aber auch das der schon compilierte 
Code unter Umständen nur für den in dem Lib Projekt angegebenen 
Controller läuft (auf Grund von, vielleicht verschiedenen Register 
Adressen), oder?

Was muss man den machen damit die Library für verschiedene Controller 
nutzbar ist, so wie z.B. bei der <avr/io.h>?
Ich hab zwar gesehen das es über #defines läuft, aber irgendwie muss das 
dann doch auch beim Library compilieren berücksichtigt werden oder 
nicht?

Das mit dem separaten angeben der Header (-I) hat das Problem übrigens 
gelöst :)

Auch wenn mir noch nicht so ganz klar ist wie man das am besten in dem 
Eclipse Lib Projekt Strukturiert.

von Karl H. (kbuchegg)


Lesenswert?

Christian schrieb:
> Ah okay danke, das bedeutet dann aber auch das der schon compilierte
> Code unter Umständen nur für den in dem Lib Projekt angegebenen
> Controller läuft (auf Grund von, vielleicht verschiedenen Register
> Adressen), oder?

Ganz genau.

> Was muss man den machen damit die Library für verschiedene Controller
> nutzbar ist, so wie z.B. bei der <avr/io.h>?

Du schmeisst dauern Header und Library durcheinander!


Eine Library ist nichts anderes als die compilierten C-Files. Aus 
praktischen Gründen, damit man nicht dauern alle C-Files einzeln mit ins 
Projekt aufnehmen muss, compiliert man die einmal und fasst dann die 
daraus entstehenden, compilierten Codeteile in einer Library zusammen.

Mit Header Files hat das so gesehen erst mal gar nichts zu tun.

Alles was du in deinem eigenen Projekt tatsächlich in Textform 
benötigst, was also der Compiler tatsächlich sehen muss, kann nicht in 
einer echten Library sein. Denn die Library wird erst vom Linker 
hinzugefügt, der sich dann aus der Lib die Funktionsrümpfe holt, die er 
braucht um das Komplettprogramm zu komplettieren.


Disclaimer: Ja, ich weiß. Hier im Forum werden oft einfach Header-Files 
als 'Library' bezeichnet, und es kratzt keinen. Aber eigentlich ist das 
nicht richtig. Eine Library im eigentlichen Sinne ist etwas anderes. 
Eine Library ist eine Sammlung von vorkompiliertem Code.

von Fabian O. (xfr)


Lesenswert?

Christian schrieb:
> Ah okay danke, das bedeutet dann aber auch das der schon compilierte
> Code unter Umständen nur für den in dem Lib Projekt angegebenen
> Controller läuft (auf Grund von, vielleicht verschiedenen Register
> Adressen), oder?

Genau. Sofern in der Lib Hardwarezugriffe stattfinden, funktioniert sie 
nur auf dem Controller, für den sie kompiliert wurde (außer die 
Registeradressen etc. stimmen zufällig überein).

> Was muss man den machen damit die Library für verschiedene Controller
> nutzbar ist, so wie z.B. bei der <avr/io.h>?
> Ich hab zwar gesehen das es über #defines läuft, aber irgendwie muss das
> dann doch auch beim Library compilieren berücksichtigt werden oder
> nicht?

Nach dem Compilieren ist von den Defines nichts mehr übrig. Streng 
genommen werden sie sogar schon vor dem Compilieren vom Preprozessor 
ersetzt.

Was möchtest Du denn mit der Lib bezwecken? Möchtest Du sie weitergeben, 
ohne dass der Empfänger den C-Quellcode sehen und verändern darf? Dann 
teile sie in einen hardwareabhängigen Teil, den Du als C-Quelltext 
weitergibst und nur den hardwareunabhängigen Teil in der kompilierten 
Lib.

Für alle anderen Einsatzwecke wäre es das sinnvollste, einfach nur den 
C-Quellcode weiterzugeben. Wenn es für Deine eigene Projekte ist, mach 
Dir einen Ordner für gemeinsamen Quellcode, den Du in die einzelnen 
Projekte als Link einfügst.

von Christian (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
>> Was muss man den machen damit die Library für verschiedene Controller
>> nutzbar ist, so wie z.B. bei der <avr/io.h>?
>
> Du schmeisst dauern Header und Library durcheinander!

Nein so meinte ich das nicht, ich meinte die AVR "Library" die hinter 
der <avr/io.h> steht. Die funktioniert ja Controller unabhängig, gibt es 
da dann, für jeden Controller eine xxx.a oder wie läuft so was? Genau so 
wie <util/delay.h>.

Fabian O. schrieb:
> Was möchtest Du denn mit der Lib bezwecken?

Im Moment arbeite ich an eigenen TWI Funktionen. Später brauche ich 
diese Funktionen für verschiedene unter Projekte. Also ein 
Multiprozessor System (das eigentliche Projekt) bei dem die 
Kommunikation über TWI läuft aber jeder Controller eine andere Aufgabe 
hat. Soll heißen, verschiedene "Projekte" aber TWI sollen sich alle aus 
der gleichen Quelle holen. Es wäre relativ umständlich wenn ich z.B. 
eine Verbesserung in der TWI Lib vornehme und dann die .c und .h für ca. 
3 Projekte erneuern muss(jeweils rein kopieren usw.).

Dachte das wär ein Typischen Anwendungsfall für eine "Library" da ich in 
diesem Fall nur die Lib und die entsprechenden Projekte neu kompilieren 
muss. Vor allem wenn mehrere Personen daran arbeiten, kann ich sagen, 
die TWI Lib ist aktuallisiert, einfach update ziehen und kompilieren.

Das Problem dabei ist dann, das es verschiedene Controller sind. Atmega 
168 / 2561 usw.

von Christian (Gast)


Lesenswert?

Fabian O. schrieb:
> Für alle anderen Einsatzwecke wäre es das sinnvollste, einfach nur den
> C-Quellcode weiterzugeben. Wenn es für Deine eigene Projekte ist, mach
> Dir einen Ordner für gemeinsamen Quellcode, den Du in die einzelnen
> Projekte als Link einfügst

Was genau meinst du mit "als Link einfügen"?

von Fabian O. (xfr)


Lesenswert?

Christian schrieb:
> Nein so meinte ich das nicht, ich meinte die AVR "Library" die hinter
> der <avr/io.h> steht. Die funktioniert ja Controller unabhängig, gibt es
> da dann, für jeden Controller eine xxx.a oder wie läuft so was? Genau so
> wie <util/delay.h>.

Die avr/io.h ist einfach nur eine Headerdatei mit Definitionen der 
Registeradressen und Namen für Bitpositionen, die man in seine eigenen 
C-Dateien einbinden kann. Da gehört keine io.c bzw. io.a dazu, die Code 
enthält.

Bei util/delay.h ist die delay-Funktion direkt in der Headerdatei als 
Inline-Funktion definiert. Die Funktion wird daher erst kompiliert, wenn 
man delay.h in eine eigene C-Datei inkludiert und sie von dort aus 
aufruft.

Christian schrieb:
> Dachte das wär ein Typischen Anwendungsfall für eine "Library" da ich in
> diesem Fall nur die Lib und die entsprechenden Projekte neu kompilieren
> muss. Vor allem wenn mehrere Personen daran arbeiten, kann ich sagen,
> die TWI Lib ist aktuallisiert, einfach update ziehen und kompilieren.

So wäre es im PC-Bereich üblich. Bei Mikrocontrollern funktioniert das 
allerdings eben wegen der Hardwareabhängigkeit in der Regel so nicht.

Christian schrieb:
> Was genau meinst du mit "als Link einfügen"?

Deine Verzeichnisstruktur könnte zum Beispiel so aussehen:
C:\AVR\Common\
  twi.c
  twi.h
C:\AVR\Project1\
  main.c
  twi_config.h
C:\AVR\Project2\
  main.c
  twi_config.h

Um twi.c und twi.h in Project1 nutzen zu können, ohne sie in das 
Projektverzeichnis zu kopieren, musst Du in AtmelStudio zwei Dinge 
machen:

1. Unter Project -> Properties -> C Compiler -> Directories den Ordner 
"C:\AVR\Common" angeben. AtmelStudio macht daraus einen relativen Pfad, 
also "..\Common". Das ist nötig, damit der Compiler die twi.h findet, 
wenn Du sie mit #include "twi.h" einbindest.

2. Im Solution Explorer Rechtsklick -> Add -> Existing Item. Im 
Dialogfenster wählst Du die Datei C:\AVR\Common\twi.c (und wenn Du 
möchtest auch twi.h) aus. Jetzt aber nicht auf "Add" klicken (das würde 
die Dateien ins Projektverzeichnis kopieren) sondern auf "Add as Link". 
Das erstellt eine Verknüpfung zu den Dateien.

Wenn Du das Projekt kompilierst, wird twi.c entsprechend den 
Projektoptionenen für die Hardware in Project1 kompiliert. Wenn Du noch 
projekt- bzw. hardwarespezifische TWI-Einstellungen vornehmen musst, zum 
Beispiel Port, Geschwindigkeit etc. kannst Du die in twi_config.h 
eintragen, die von twi.c aus inkludiert wird.

Das gleiche machst Du in Project2. Wenn Du jetzt in twi.c oder twi.h 
etwas änderst, stehen die Änderungen automatisch für alle Projekte zur 
Verfügung, sobald das Projekt neu kompiliert wird. Dank Makefile wird 
twi.c übrigens nur neu kompiliert, wenn sich an twi.c, twi.h oder 
twi_config.h etwas ändert.

von Fabian O. (xfr)


Lesenswert?

Mir ist gerade noch aufgefallen, Du verwendest ja Eclipse statt 
AtmelStudio. Dort geht es aber vom Prinzip her genauso. Soweit ich mich 
erinnere kannst Du in Eclipse sogar einfach den ganzen Ordner Common als 
Link in das Projekt einfügen, ohne die einzelnen Dateien darin auswählen 
zu müssen.

von Oliver (Gast)


Lesenswert?

Die Lib zur AVR/io.h ist die avrlibc, das ist aber nicht nur eine Lib, 
daß sind mehrere verschiedene, für jede AVR-Familie eine. Durch etwas 
"Magie" im Hintergrund wird da jeweils die passende für den ausgewählten 
AVR beim linken hinzugelinkt.
Eine für alle funktioniert da auch nicht.

Oliver

von Christian (Gast)


Lesenswert?

Fabian O. schrieb:
> Die avr/io.h ist einfach nur eine Headerdatei mit Definitionen der
> Registeradressen und Namen für Bitpositionen, die man in seine eigenen
> C-Dateien einbinden kann. Da gehört keine io.c bzw. io.a dazu, die Code
> enthält.

Oh okay, das war mir jetzt erst mal nicht so bewusst, dachte nach den 
"#ifdef" in der <avr/io.h> kommen vielleicht nachfolgend irgendwann 
includes zu denen eine controller spezifische xxx.a gehört. Aber gut, 
jetzt weiß ich wie das läuft. Und danke für die Idee mit dem verlinken, 
funktioniert problemlos, das mit der separaten config werde ich später 
probieren, aber die Idee ist gut. Danke.

Und das Verlinken von Ordnern in Eclipse funktioniert auch, wär ich 
soooo jetzt erst mal nicht drauf gekommen :)


Oliver schrieb:
> Durch etwas
> "Magie" im Hintergrund wird da jeweils die passende für den ausgewählten
> AVR beim linken hinzugelinkt.

So etwas in der Art hätte ich eigentlich auch vermutet.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.