Forum: Compiler & IDEs Eclipse: was bedeutet diese Fehlermeldung?


von Uhu U. (uhu)


Lesenswert?

Ein Build all produziert folgende Fehlermeldung:
1
make all 
2
Building target: ff.elf
3
Invoking: AVR C Linker
4
avr-gcc -Wl,-Map,ff.map -mmcu=atmega88 -o"ff.elf"  ./ff.o   
5
/usr/local/avr/lib/gcc/avr/4.6.0/../../../../avr/bin/ld: cannot find -lgcc
6
collect2: ld returned 1 exit status
7
make: *** [ff.elf] Error 1

In den zum make-System gehörenden Files im Projekt kann ich den String 
-lgcc nicht finden.

: Verschoben durch User
von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Das hat nix mit Eclipse zu tun, sondern der Linker bemängelt, dass er 
die Bibliothek 'gcc' nicht finden kann. Woher er diese beziehen sollte 
müsstest du mal schauen.

(Ich verschieb' das mal nach GCC)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Die libgcc ist ein integraler Bestandteil von gcc. Sieht nach einer 
fehlerhaften/unvollständigen Installation aus.

Das -lgcc kommt nicht aus dem Makefile, sondern von den specs. 
Vielleicht erfährst du mehr mit einem Aufruf mit -v.

von Uhu U. (uhu)


Lesenswert?

Ich hab den avr-gcc selbst compiliert - laufen tut er, aber eine 
libgcc.so gibt es nirgends.

von Rolf Magnus (Gast)


Lesenswert?

Uhu Uhuhu schrieb:
> Ich hab den avr-gcc selbst compiliert - laufen tut er, aber eine
> libgcc.so gibt es nirgends.

Die wird auch eher libgcc.a heißen. Die muß da sein. Ohne läuft der 
Compiler zwar, aber du wirst keine damit erzeugten Programme gelinkt 
bekommen.

von Uhu U. (uhu)


Lesenswert?

Es sollte einen Teilbaum unter /usr/lib/gcc/avr/ geben - der fehlt bei 
mir komplett.

Aus welchem Paket wird der generiert?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Die libgcc ist eine Target-Bibliothek, du wirst kaum einen dynamischen 
Linker auf dem AVR laufen haben ;-)

Die Anatomie einer Cross-GCC-Installation sieht folgendermassen aus:
1
$prefix/bin             - Programme, die der Anwender auf $host aufruft,
2
                          um Programme für $target zu erstellen
3
$prefix/$target/bin     - GCC-verwendbare Executables (binutils)
4
$prefix/$target/include - Header für $target
5
$prefix/$target/lib     - (Multi)Libs für $target
6
$prefix/libexec/gcc/$target/$gcc-version 
7
                        - Executables für GCC-version (cc1, cc1plus, ...)
8
$prefix/lib/gcc/$target/$gcc-version
9
                        - (Multi)Libs für GCC-version für $target

Die unterschiedlichen libgcc.a steht also in
$prefix/lib/gcc/$target/$gcc-version
für jede Multilibausprägung gibt es eine.

von Uhu U. (uhu)


Lesenswert?

Johann L. schrieb:
> Die unterschiedlichen libgcc.a steht also in
> $prefix/lib/gcc/$target/$gcc-version
> für jede Multilibausprägung gibt es eine.

Womit werden die generiert?

Unter http://ns2.canonical.com/de/lucid/amd64/gcc-avr/filelist findet 
man den von dir beschriebenen Baum von libs, der bei mir fehlt.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Uhu Uhuhu schrieb:

> Womit werden die generiert?

Die gehören zu GCC, wie gesagt. Die werden mit dem jeweiligen 
Cross-Compiler erzeugt. Die configure-Einstellungen hast du ja und 
siehtst es in den Build-Ausgaben. Die libgcc wird nach den Compilern 
(cc1, cc1plus, cc1obj, ...() generiert und diese nach 
gmp/mpc/mpfr/libelf.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Der Build der libgcc kann auch von Hand angestossen werden, z.B. mit
1
make clean-target-libgcc
2
make all-target-libgcc
3
make install-target-libgcc

Im normalen build/install werden diese Subtargets automatisch 
ausgeführt. Erzeugt werden die Multilibs nach $build/$target.

von Uhu U. (uhu)


Lesenswert?

Ich habe jetzt den arv-gcc 4.6.0 nochmal komplett neu generiert. Ein 
Baum von libgcc.a-Bibliotheken entsteht dabei nicht.

Stattdessen wird unter /usr/local/avr/avr/lib/ folgender Inhalt 
generiert:
1
drwxr-xr-x 2 root root    4096 2011-05-13 20:10 avr25
2
drwxr-xr-x 2 root root    4096 2011-05-13 20:10 avr3
3
drwxr-xr-x 2 root root    4096 2011-05-13 20:10 avr31
4
drwxr-xr-x 2 root root    4096 2011-05-13 20:10 avr35
5
drwxr-xr-x 2 root root    4096 2011-05-13 20:10 avr4
6
drwxr-xr-x 2 root root    4096 2011-05-13 20:10 avr5
7
drwxr-xr-x 2 root root    4096 2011-05-13 20:10 avr51
8
drwxr-xr-x 2 root root    4096 2011-05-13 20:10 avr6
9
-rw-r--r-- 1 root root    3540 2011-05-13 20:10 crt86401.o
10
-rw-r--r-- 1 root root    3580 2011-05-13 20:10 crtc8534.o
11
-rw-r--r-- 1 root root    3060 2011-05-13 20:10 crts1200.o
12
-rw-r--r-- 1 root root    3680 2011-05-13 20:10 crts2313.o
13
-rw-r--r-- 1 root root    3352 2011-05-13 20:10 crts2323.o
14
-rw-r--r-- 1 root root    3808 2011-05-13 20:10 crts2333.o
15
-rw-r--r-- 1 root root    3352 2011-05-13 20:10 crts2343.o
16
-rw-r--r-- 1 root root    3828 2011-05-13 20:10 crts4414.o
17
-rw-r--r-- 1 root root    3808 2011-05-13 20:10 crts4433.o
18
-rw-r--r-- 1 root root    3996 2011-05-13 20:10 crts4434.o
19
-rw-r--r-- 1 root root    3828 2011-05-13 20:10 crts8515.o
20
-rw-r--r-- 1 root root    3996 2011-05-13 20:10 crts8535.o
21
-rw-r--r-- 1 root root    3100 2011-05-13 20:10 crttn11.o
22
-rw-r--r-- 1 root root    3140 2011-05-13 20:10 crttn12.o
23
-rw-r--r-- 1 root root    3640 2011-05-13 20:10 crttn13.o
24
-rw-r--r-- 1 root root    3264 2011-05-13 20:10 crttn15.o
25
-rw-r--r-- 1 root root    3352 2011-05-13 20:10 crttn22.o
26
-rw-r--r-- 1 root root    4016 2011-05-13 20:10 crttn2313.o
27
-rw-r--r-- 1 root root    3932 2011-05-13 20:10 crttn24.o
28
-rw-r--r-- 1 root root    3848 2011-05-13 20:10 crttn25.o
29
-rw-r--r-- 1 root root    4016 2011-05-13 20:10 crttn261.o
30
-rw-r--r-- 1 root root    3724 2011-05-13 20:10 crttn26.o
31
-rw-r--r-- 1 root root    3140 2011-05-13 20:10 crttn28.o
32
-rw-r--r-- 1 root root    3996 2011-05-13 20:10 crttn44.o
33
-rw-r--r-- 1 root root    3912 2011-05-13 20:10 crttn45.o
34
-rw-r--r-- 1 root root    4080 2011-05-13 20:10 crttn461.o
35
-rw-r--r-- 1 root root    3996 2011-05-13 20:10 crttn84.o
36
-rw-r--r-- 1 root root    3912 2011-05-13 20:10 crttn85.o
37
-rw-r--r-- 1 root root    4080 2011-05-13 20:10 crttn861.o
38
drwxr-xr-x 2 root root    4096 2011-05-10 23:28 ldscripts
39
-rw-r--r-- 1 root root 1041686 2011-05-13 20:10 libc.a
40
-rw-r--r-- 1 root root  145102 2011-05-13 20:10 libm.a
41
-rw-r--r-- 1 root root   14278 2011-05-13 20:10 libprintf_flt.a
42
-rw-r--r-- 1 root root    8090 2011-05-13 20:10 libprintf_min.a
43
-rw-r--r-- 1 root root   16248 2011-05-13 20:10 libscanf_flt.a
44
-rw-r--r-- 1 root root   10460 2011-05-13 20:10 libscanf_min.a

Dieser Baum entsteht auch, wenn man deine Kommandos
   make clean-target-libgcc
   make all-target-libgcc
   make install-target-libgcc
manuell eingibt.

Offenbar wurde da irgenwas in der Bibliotheksstruktur geändert, was 
Eclipse noch nicht kennt.

von Uhu U. (uhu)


Angehängte Dateien:

Lesenswert?

Hier ist der Output der make-Kommandos.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Eclipse hat die interne Struktur von GCC nicht zu interessieren.

> cd /tmp/gcc-4.6.0/obj-avr

Generierung in Unterverzeichnissen des Quellbaums wird nicht 
unterstützt.

Optionen für configure wären hilfreich, so ist das doch rumgestocher. 
Wieso generiest du als root???

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ist prefix=/usr/local oder /use/local/avr?

In dem Falle ist nicht mehr zu unterscheiden, ob /use/local/avr das 
Installationsverzeichnis ist oder /use/local und nur avr darin zur 
Installation gehört. Vermeide solche Mehrdeutigkeiten!

von Uhu U. (uhu)


Lesenswert?

Ich habe mich - außer alles als root zu machen - an diese Anleitung 
gehalten: 
http://www.rn-wissen.de/index.php/Avr-gcc_und_avrdude_installieren#avr-gcc

Da die Generierung in /tmp lief, sollte es doch eigentlich egal sein, ob 
config und make als root laufen, oder nicht.

Ich habs vorher auch schon ohne root-Rechte gemacht - kein Unterschied.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Uhu Uhuhu schrieb:

> Stattdessen wird unter /usr/local/avr/avr/lib/ folgender Inhalt
> generiert:

Das ist die avr-libc.

die libgcc wäre unter /usr/local/avr/lib/gcc/4.6.0

Wurde da schon mal ein avr-gcc installiert, möglicherweise unter 
$prefix=/usr/local? Merkst du was?

Nochmal: Generierung in Sub-Verzeichnissen wird nicht unterstützt.

Da du eine .0 kaum produktiv einsetzten werden willst, wäre es 
sinnvoller nicht eine (evtl. vorhandene) Installation zu 
überschreiben/versäbeln sondern in ein eigenes Verzeichnis zu 
Installieren, das kann auch unterhalb von $HOME sein.

von Uhu U. (uhu)


Lesenswert?

Johann L. schrieb:
> Wurde da schon mal ein avr-gcc installiert, möglicherweise unter
> $prefix=/usr/local? Merkst du was?

Es war schon der zu Ubuntu 10.04 gehörende avr-gcc installiert, 
allerdings unter /opt. Den hatte ich vorher deinstalliert und dann unter 
/usr/local/avr etliche Anläufe gemacht.

Ich hab jetzt nochmal als normaler User unter /tmp/obj-avr generiert und 
als root installiert (geht eh nicht anders).

Jetzt habe ich libgcc's unter /usr/local/avr/lib/gcc/avr/4.6.0 und jetzt 
gehts...

Vielen Dank für die Hilfe.

> Da du eine .0 kaum produktiv einsetzten werden willst,

Sind das Betas? Ich hab mir unter ftp://ftp.gnu.org/gnu/gcc/ den mit der 
höchsten Versionsnummer gegriffen...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Uhu Uhuhu schrieb:

> Ich hab jetzt nochmal als normaler User unter /tmp/obj-avr generiert und
> als root installiert (geht eh nicht anders).

Kommt auf den Ort des Installationsverzeichnisses an.

> Jetzt habe ich libgcc's unter /usr/local/avr/lib/gcc/avr/4.6.0 und jetzt
> gehts...

Also war's die Generierung in einem Unterverzeichnis der GCC-Quellen:

http://gcc.gnu.org/install/configure.html
> First, we highly recommend that GCC be built into a separate
> directory from the sources which does not reside within the source
> tree.

>> Da du eine .0 kaum produktiv einsetzten werden willst,
>
> Sind das Betas? Ich hab mir unter ftp://ftp.gnu.org/gnu/gcc/ den mit der
> höchsten Versionsnummer gegriffen...

Was heisst schon "beta"? x.y.0 ist die erste Release, die auf die Welt 
losgelassen wird. Bis zur Release ist ein .0-GCC praktisch nur gegen die 
eigene Testsuite gelaufen. Ein paar Projekte verwenden auch aktuelle GCC 
Snapshots zum Testen, wie SPEC-Tests, Mozilla oder HIRLAM (gfortran, 
Wettervorhersage für Europa). Ich weiß aber von keinem AVR-Entwickler, 
der zeitnah Snapshots testet. Bestenfalls Jörg, um die avr-libc zu 
testen/generieren.

Aufgrund der praktisch nicht-vorhandenen avr-gcc-Entwickler/Entwicklung 
gammeln allerdings auch bekannte Fehler oder Optimierungspatzer 
teilweise ziemlich lang in .1+ Versionen auch älterer avr-gcc Releases 
rum. So wird dir wahrscheinlich schon aufgefallen sein, daß DWARF2 
(-gdwarf-2) mit avr-gcc-4.6.0 nicht wirklich produktiv ist ;-)

Teilweise verwenden Distributionen auch eigene Patchsets. Einerseits, 
weil die Patches nicht immer unter GPL stehen, und andererseits, weil 
die einfacher in GCC zu integrieren sind (allersings schwerer zu 
supporten, weil ein Patch immer nur auf eine bestimmte GCC-Version wie 
x.y.z passt und teiweise das Vorhandensein anderer Patches voraussetzt).

von Bildformate (Gast)


Lesenswert?

Johann L. schrieb:
> Die Anatomie einer Cross-GCC-Installation sieht folgendermassen aus:
> [...]
Das klingt nach relevanten Informationen für die Artikelsammlung, kannst 
du das da falls sinnvoll irgendwo einbauen?

(Ich verstehe nur Bahnhof, deshalb will ich nicht selber an der falschen 
Stelle basteln.)

von Uhu U. (uhu)


Lesenswert?

Ich denke, es würde reichen, wenn wir hier einen Abschnitt über das 
compilieren des avr-gcc in den entsprechenden Artikel 
(http://www.mikrocontroller.net/articles/AVR_und_Linux) packen, der die 
Fehler bei RoboterNETZ nicht enthält, über die ich geflogen bin.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Uhu Uhuhu schrieb:
> Ich denke, es würde reichen, wenn wir hier einen Abschnitt über das
> compilieren des avr-gcc in den entsprechenden Artikel
> (http://www.mikrocontroller.net/articles/AVR_und_Linux) packen, der die
> Fehler bei RoboterNETZ nicht enthält, über die ich geflogen bin.

Sinnvoll wäre es, den Artikel in rn-wissen zu korrigieren (ist ein Wiki 
wo sich jeder anmelden kann, wie hier auch) abstatt das Thema nochmal zu 
beackern und die Stolperfalle dort zu lassen nach dem 
St-Florians-Prinzip ;-)

Eine Warnung/Verweis auf die Doku reicht je schon, und das Rumgefuchtel 
mit den Pfaden braucht's eigentlich auch net.

Zudem gibt's auch fertige Build-Skripte, z.B von Bingo600 bei den 
avr-freaks.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:

> Ich weiß aber von keinem AVR-Entwickler,
> der zeitnah Snapshots testet. Bestenfalls Jörg, um die avr-libc zu
> testen/generieren.

Auch nur sporadisch, um die Compilierbarkeit selbst sicherzustellen,
wie letztlich nach dem const/progmem internal compiler error.
Zumindest habe ich immer einen ausgecheckten SVN trunk rumliegen,
den ich gelegentlich mal aktualisiere und dann wenigstens gegen sich
selbst compiliere.

Weil wir gerade dabei sind, Georg, gibt's irgendwo eine Anleitung,
wie man den GCC-trunk "bootstrappt"?  Einen ./bootstrap-Script gibt
es leider nicht, auch kein ./configure im SVN, und der ganze Kram
scheint ja pingeligst zu sein bezüglich der zu verwendenden
autofoobar-Versionen.  Ich möchte gern mal gucken, wie man die
libstdc++ compilierbar bekommt, dazu muss ich allerdings wohl den
autofoobar-Krempel anfassen ...

von Rolf Magnus (Gast)


Lesenswert?

Die libstdc++? Meintest du die libsupc++? Erstere enthält eigentlich 
nicht viel, das man sinnvoll auf einem AVR nutzen könnte.
Für C++ wäre aber erstmal wünschenswert, wenn vtables nicht im RAM 
stehen müßten. Als ich mir das damals mal in den GCC-Sourcen angesehen 
hab, war's aber (zumindest für mich) ein recht aussichtsloses 
Unterfangen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Die libstdc++? Meintest du die libsupc++? Erstere enthält eigentlich
> nicht viel, das man sinnvoll auf einem AVR nutzen könnte.

Naja, Container und all sowas müssten auch auf einem AVR gehen,
die sind doch da auch drin, oder?  Zumindest unterscheidet GCC
dabei zwischen "freestanding" und "hosted", man könnte ja zumindet
freestanding mal probieren.

> Für C++ wäre aber erstmal wünschenswert, wenn vtables nicht im RAM
> stehen müßten.

Ist allerdings 'ne ganz andere Baustelle, da das wohl ziemlich tief
in die Codegenerierung des Compilers eingreifen dürfte.

von Rolf Magnus (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Rolf Magnus schrieb:
>> Die libstdc++? Meintest du die libsupc++? Erstere enthält eigentlich
>> nicht viel, das man sinnvoll auf einem AVR nutzen könnte.
>
> Naja, Container und all sowas müssten auch auf einem AVR gehen,
> die sind doch da auch drin, oder?

Schon, aber die nutzen allesamt dynamischen Speicher, und den nicht 
allzu knapp.

> Zumindest unterscheidet GCC dabei zwischen "freestanding" und "hosted",
> man könnte ja zumindet freestanding mal probieren.

Bleibt bei freestanding überhaupt was von der libstdc++ übrig?

>> Für C++ wäre aber erstmal wünschenswert, wenn vtables nicht im RAM
>> stehen müßten.
>
> Ist allerdings 'ne ganz andere Baustelle, da das wohl ziemlich tief
> in die Codegenerierung des Compilers eingreifen dürfte.

Ja, richtig. Das habe ich auch festgestellt. Verschiedene Arten von 
Speicher sind einfach so nicht vorgesehen. Aber Polymorphie könnte auch 
auf den kleinen AVRs schon praktisch sein, wenn sie nicht so viel RAM 
fressen würde.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:

>> Naja, Container und all sowas müssten auch auf einem AVR gehen,
>> die sind doch da auch drin, oder?
>
> Schon, aber die nutzen allesamt dynamischen Speicher, und den nicht
> allzu knapp.

Was ja kein k.o.-Kriterium ist.  Wenn man ein dynamisches Problem
hat, lässt es sich nur dynamisch lösen.  Es ist dann ziemlich egal,
ob im Zweifelsfalle kein Platz mehr im prä-allozierten Array mehr
ist oder keiner mehr im Heap, der Effekt ist der gleiche.

>> Zumindest unterscheidet GCC dabei zwischen "freestanding" und "hosted",
>> man könnte ja zumindet freestanding mal probieren.
>
> Bleibt bei freestanding überhaupt was von der libstdc++ übrig?

Habe ich noch nicht geschaut. ;-)  Ich hatte erstmal die "hosted"-
Variante getestet, aber der fehlt ziemlich viel, und es hat wenig
Sinn, für all das auch stubs zu implementieren.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Johann L. schrieb:
>
>> Ich weiß aber von keinem AVR-Entwickler,
>> der zeitnah Snapshots testet. Bestenfalls Jörg, um die avr-libc zu
>> testen/generieren.
>
> Auch nur sporadisch, um die Compilierbarkeit selbst sicherzustellen,
> wie letztlich nach dem const/progmem internal compiler error.
> Zumindest habe ich immer einen ausgecheckten SVN trunk rumliegen,
> den ich gelegentlich mal aktualisiere und dann wenigstens gegen sich
> selbst compiliere.

Einen lauffähigen Cross-GCC bekommt man auch ohne Bootstrap bzw. eine 
Host-GCC gleicher Version zu verwenden. Der einzuge Nachteil sind 
Warnungen bei der Generierung.

> Weil wir gerade dabei sind, Georg, gibt's irgendwo eine Anleitung,
> wie man den GCC-trunk "bootstrappt"?  Einen ./bootstrap-Script gibt
> es leider nicht, auch kein ./configure im SVN, und der ganze Kram
> scheint ja pingeligst zu sein bezüglich der zu verwendenden
> autofoobar-Versionen.  Ich möchte gern mal gucken, wie man die
> libstdc++ compilierbar bekommt, dazu muss ich allerdings wohl den
> autofoobar-Krempel anfassen ...

Für autozeug braucht man teilweise die exakte Version, die GCC möchte. 
Keine ältere und keine neuere. Sollte aber angemeckert werden.

Ein aus dem aktuellen configure.ac generiertes toplevel-configure ist 
vorhanden, siehe

http://gcc.gnu.org/viewcvs/trunk/configure?view=markup

Nen Bootstrap hab ich noch nie gemacht; scheitert "make bootstrap"? Auch 
einzelne Stages gehen mit "make stage1-bubble". GCC-Generierung schlägt 
fehl wenn bestimmte Umgebungsvariablen gesetzt sind wie CC. Falls allen 
scheitert frag auf gcc-help, Ian ist da immer sehr hilfsbereit. Evtl. 
hilft auch ein Blick ins Toplevel Makefile in $build, hal allerdings 
weit über 1E5 Zeilen.

Rolf Magnus schrieb:
> Für C++ wäre aber erstmal wünschenswert, wenn vtables nicht im RAM
> stehen müßten. Als ich mir das damals mal in den GCC-Sourcen angesehen
> hab, war's aber (zumindest für mich) ein recht aussichtsloses
> Unterfangen.

Die vtables ins Flash zu legen wär wohl noch machbar; das Problem werden 
aber garantiert die Zugriffe, weil man anhand der Adresse nicht 
unterscheiden kann, wo was liegt (selbst wenn man es anhand der Adresse 
unterscheiden könnte, will man nicht zur Laufzeit entscheiden, ob ein 
LPM oder ein LD zu nehmen ist). Momentan ist .rodata in .data, siehe 
gcc/config/avr/avr.c:avr_asm_init_sections(), weil das die einzige 
Möglichkeit ist, laufbare Programme zu erzeugen. Alles anders erfordert 
bislang das PROGMEM/pgm_ Gewurschtel.

Selbst mit Named Address Spaces (NAS) wird das nicht einfach, und wie 
man da Sachen wie memcpy realisiert, hab ich auch keine Idee. Der 
Prototyp muss nämlich stimmen, und in C geht das nur über eine eigene 
Funktion wie memcpy_P. Eine NAS-Implementierung hab ich irgendwo 
rumfliegen, und der erzeugte Code für einfache Beispiele ist auch 
korrekt uns sinnig, aber gerade bei Initializern gibt's keine 
ISO-Möglichkeit zu sagen, wo der liegen soll. Man bräuchte sowas wie 
Suffixe von z.B. String-Literalen.

Bevor man die vtables anpackt, wäre also erst mal ein NAS-Support zu 
machen, um überhaupt ausdrücken zu können, wo die Tabellen überhaupt 
liegen/wie darauf zugegriffen wird. Ob das alles dann im Sandkasten des 
AVR-Backend machbar wäre, ist ne ganz andere Geschichte.

Aber auch ohne vtables wären NAS ein Fortschritt, weil es typsicheren 
Zugriff aufs Flash ermöglicht ohne das pgm_ Zeugs.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:

> Einen lauffähigen Cross-GCC bekommt man auch ohne Bootstrap
> bzw. eine Host-GCC gleicher Version zu verwenden.

Sorry, zwei verschiedene Bedeutungen von "bootstrap" hier, ich hatte
vergessen, dass GCC das Wort bei einem Crosscompiler ja bereits belegt
hat.

Normalerweise haben autoconf/automake-basierte Softwareprojekte einen
Script namens "bootstrap" oder auch "autogen.sh", in dem die Abfolge
der auto-Kommandos aufgeschrieben ist.  Sowas fehlt bei GCC.

> Für autozeug braucht man teilweise die exakte Version, die GCC
> möchte.  Keine ältere und keine neuere. Sollte aber angemeckert
> werden.

Ja, allerdings ist halt ohne den genannten Script die Frage, ob man
die jeweiligen Tools auch mit den korrekten Optionen und in der
richtigen Reihenfolge benutzt hat ...

> Ein aus dem aktuellen configure.ac generiertes toplevel-configure ist
> vorhanden

Ja, war mein Fehler, das nützt mir halt nichts, wenn ich am
configure.ac herumschrauben muss.

> Eine NAS-Implementierung hab ich irgendwo
> rumfliegen, und der erzeugte Code für einfache Beispiele ist auch
> korrekt uns sinnig, ...

Oh, das ist doch mal 'ne gute Nachricht!  Auf named address spaces war
ich schon immer neidisch. ;-)  Entspricht das, was bei GCC da passiert,
eigentlich dem TR 18037 ("Embedded C")?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Johann L. schrieb:
>
>> Einen lauffähigen Cross-GCC bekommt man auch ohne Bootstrap
>> bzw. eine Host-GCC gleicher Version zu verwenden.
>
> Sorry, zwei verschiedene Bedeutungen von "bootstrap" hier, ich hatte
> vergessen, dass GCC das Wort bei einem Crosscompiler ja bereits belegt
> hat.
>
> Normalerweise haben autoconf/automake-basierte Softwareprojekte einen
> Script namens "bootstrap" oder auch "autogen.sh", in dem die Abfolge
> der auto-Kommandos aufgeschrieben ist.  Sowas fehlt bei GCC.
>
>> Für autozeug braucht man teilweise die exakte Version, die GCC
>> möchte.  Keine ältere und keine neuere. Sollte aber angemeckert
>> werden.
>
> Ja, allerdings ist halt ohne den genannten Script die Frage, ob man
> die jeweiligen Tools auch mit den korrekten Optionen und in der
> richtigen Reihenfolge benutzt hat ...
>
>> Ein aus dem aktuellen configure.ac generiertes toplevel-configure ist
>> vorhanden
>
> Ja, war mein Fehler, das nützt mir halt nichts, wenn ich am
> configure.ac herumschrauben muss.

Zum Rumspielen genügt ja erstmal, configure zu ändern.
1
# Disable libstdc++-v3 for some systems.
2
case "${target}" in
3
...
4
  avr-*-*)
5
    noconfigdirs="$noconfigdirs target-libstdc++-v3"
6
    ;;
7
esac

>> Eine NAS-Implementierung hab ich irgendwo
>> rumfliegen, und der erzeugte Code für einfache Beispiele ist auch
>> korrekt und sinnig, ...
>
> Oh, das ist doch mal 'ne gute Nachricht!  Auf named address spaces war
> ich schon immer neidisch. ;-)  Entspricht das, was bei GCC da passiert,
> eigentlich dem TR 18037 ("Embedded C")?

Das ist die Grundlage der Implementierung, allerdings ist sie nicht 
vollständig umgesetzt. Zum Beispiel fehlen die Teile, die es der 
Applikation erlauben, eigenen Code für Speicherzugriffe einzuklinken. 
Damit wäre es auf Applikationsebene möglich, typsichere 
Ersatzfunktionen für zB eeprom_read/write_byte zu schreiben. Für jeden 
address space gibt man eigene Byte-Zugriffsfunktionen an, die dann per 
Funktionsaufruf oder Inline eingebunden werden.

Der ursprüngliche TR18037-Implementierung stammt von Michael Meissner 
(IBM), sie wurde für I/O-Zugriffe für einen Multi-Code (SPU) gemacht. 
Leider hat er jetzt andere Aufgabenbereiche.

Leider hat NAS auch einige Nachteile, zB würde in
1
const char __pgm * p = "FOO";

"FOO" in .rodata landen, also im RAM, entgegen der Intention des Codes.

Wie sinnvoll NAS in avr-gcc wäre, weiss ich nicht. Die Leute sind ja 
eher auf jedes Byte an erzeugtem Code scharf als an "sauberen" Quellen. 
Ausserdem müsste man sich genau überlegen, wie das mit dem momentanen 
avr-libc Interface zusammenpasst, denn wenn man die _P Funktionen mit 
-Wcast-qual verwendet, bekäm man 1000 Warnungen. Die avr-libc-Interna 
müssten nicht geändert werden, da pgm_ ja weiterhin funktioniert.

Allerdings ist es nicht ganz einfach, dem GCC einen Adressierungsmodus 
beizubringen, der für größere Typen ausschliesslich post-increment auf Z 
unterstützt. Um das effizient zu machen, brauch't wohl Magie, die ich 
nicht hab. Bestenfalls Anatoly oder Dennis oder GCC-Gurus, die mit AVR 
nix am Hut haben...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Johann L. schrieb:
>
>> Eine NAS-Implementierung hab ich irgendwo
>> rumfliegen, und der erzeugte Code für einfache Beispiele ist auch
>> korrekt uns sinnig, ...
>
> Oh, das ist doch mal 'ne gute Nachricht!  Auf named address spaces war
> ich schon immer neidisch. ;-)

Hast Du die Implementierung mal angetestet?

Es gibt einen MS-Windows Snapshot avr-gcc-4.7-pgm-179594-mingw32.zip in 
[1] oder wenn es Dir genehmer ist unter Linux zu generieren dann nimmst 
Du die Patches von [2] zu trunk r175594. Eine

[1] http://sourceforge.net/projects/mobilechessboar/files/
[2] http://gcc.gnu.org/PR49868

Die Syntax bei offensichtlicher Semantik ist dann:
1
#define _PGM const __pgm 
2
#define PGM_STR(X) ((_PGM char[]) { X }) 
3
4
int _PGM a = 1; 
5
char _PGM *pstr = PGM_STR ("123"); 
6
long _PGM l[] = { 'a', 'b', 'c'}; 
7
8
char get_1 (char _PGM **p)       { return **p; } 
9
char get_2 (char _PGM * _PGM *p) { return **p; } 
10
char get_3 (char * _PGM *p)      { return **p; } 
11
char get_4 (char **p)            { return **p; } 
12
13
int main (void) 
14
{ 
15
    return a + pstr[2] + l[1]; 
16
}

Wieviel Aufwand wäre das für die avr-libc?
1
#ifndef _PGM
2
#define _PGM const
3
#endif
4
5
#define printf_P(FMT,x...) __printf_P((_PGM char*)FMT , ##x)
Die Implementierung in der avr-libc müsste sich nicht ändern; der 
Makro/Cast dient nur dazu, das ganze typsicher zu haben — zumindest für 
C99, wo es variadische Makros hat.

_PGM als Built-in Makro in avr-gcc ist kein Problem, wäre dann analog zu 
den Built-in Makros für die AVR-Built-ins.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nun, am liebsten wäre es mir, wenn der Compiler über einen
Präprozessor-Makro "erzählen" kann, dass er named address spaces
unterstützt, sowas à la __GCC_FEATURE_NAS oder so.  Dann könnte
man die avr-libc entsprechend automatisch anpassen lassen.  Dann
hätten auch die bisherigen Typ-Namen für pgmspace wieder Sinn,
die Eric meiner Meinung nach ein wenig voreilig "deprecated"
hat, d. h. man könnte sowas machen:
1
#if defined(__GCC_FEATURE_NAS)
2
#define PROGMEM __pgm
3
#else /* traditional attribute-based implementation */
4
#define PROGMEM __ATTR_PROGMEM__
5
#endif

Wenn es sich darauf herunterbrechen ließe, wäre mir das wohl das
liebste.  Der PROGMEM-Makro wird insgesamt wohl recht häufig in der
Praxis genutzt.

Wenn das mit dem Makro partout nicht geht, weil es gegen irgendeine
GCC-Policy verstößt, dann könnte man es noch via configure
feststellen lassen, ob der Compiler das Feature kennt oder nicht,
so ähnlich, wie <util/delay.h> das bereits für
__builtin_avr_delay_cycles macht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Nun, am liebsten wäre es mir, wenn der Compiler über einen
> Präprozessor-Makro "erzählen" kann, dass er named address spaces
> unterstützt, [...]

Kein Problem; ist nur ein Einzeiler das und für die avr-Builtins gibt's 
ja auch Defines.

> Dann hätten auch die bisherigen Typ-Namen für pgmspace wieder
> Sinn, die Eric meiner Meinung nach ein wenig voreilig
> "deprecated" hat [...]

Die Deprecation geschieht völlig zu Recht. Wobei ich da befangen bin, 
weil die Deprecation befürworte und angeregt habe...

>d. h. man könnte sowas machen:
1
> #if defined(__GCC_FEATURE_NAS)
2
> #define PROGMEM __pgm
3
> #else /* traditional attribute-based implementation */
4
> #define PROGMEM __ATTR_PROGMEM__
5
> #endif

Wenn das Buildin-Makro _Pgm heisst, geht doch einfach
1
#ifdef _Pgm
2
#define __AVR_LIBC__PGM __pgm
3
#else
4
#define __AVR_LIBC__PGM
5
#endif
6
7
extern void printf_P (const __AVR_LIBC__PGM char*, ...); 
8
...

PROGMEM würde ich aus Kompatibilitätsgründen nicht ersetzen.

Sinn der Header ist ja nur, typsicher zu sein. Wobei ich teilweise 
Warnungen vom Compiler vermisse wenn __pgm fehlt.

Und leider ist es alles andere als intuitiv, einen Zeiger mit einem 
String-Literal tzu initialisieren, das im Flash zu liegen kommen soll. 
Hier wird neben dem alten PSTR, für das es kein Ersetz gibt, noch sowas 
wie PGM_STR benötigt:
1
#include <avr/pgmspace.h>
2
3
#define PGM_STR(X) ((const __pgm char[]) { X })
4
5
const __pgm char * gstr = PGM_STR ("123");
6
7
const __pgm char * get_pstr (void)
8
{
9
    return (const __pgm char*) PSTR ("abc");
10
}
Die eine Variante funktioniert nur ausserhalb von Funktionen, die andere 
nur innerhalb.

> Wenn es sich darauf herunterbrechen ließe, wäre mir das wohl das
> liebste.  Der PROGMEM-Makro wird insgesamt wohl recht häufig in der
> Praxis genutzt.

Hier besteht kein Grund es für den Anwender zu ändern; Attribut progmem 
bleibt ja weiterhin erhalten.

> Wenn das mit dem Makro partout nicht geht, weil es gegen irgendeine
> GCC-Policy verstößt,

Kein Problem, s.o.
> wie <util/delay.h> das bereits für __builtin_avr_delay_cycles machthttp://gcc.gnu.org/onlinedocs/gcc/AVR-Built_002din-Functions.html#AVR-Built_002din-Functions
1
#if defined (__BUILTIN_AVR_DELAY_CYCLES)

Wie sieht's mit Flash jenseits von 64k aus?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49868#c6

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Übrigens ist das Patch, auf dem der avr-gcc-Support von AS __pgm 
aufbaut, inzwischen im Review. Und da Denis prinzipiell nichts gegen 
einen AS-Support hat, steht dem wohl auch nichts entgegen.

Bleibt nur die Frage, wie das Kind heissen soll. Eric meint __flash.

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.