Hallo, ich nutze WINAVR, Version: WINAVR20071221. Der verwendete Controller ist ein MEGA32. Ich wollte mal zum ausprobieren die "Luxus"-printf Variante verwenden, also die auch die Fließkommaausgaben verarbeiten kann. Nun habe ich in der Doku der AVR-LIBC nachgelesen, wie man die Libray dazu linkt. Geschrieben steht dort folgendes: If the full functionality including the floating point conversions is required, the following options should be used: -Wl,-u,vfprintf -lprintf_flt -lm Das habe ich gemacht, wie man unten sieht. Leider gibt es auch Fehlermeldungen, so dass da linken nicht funktioniert. Building target: Loetst.elf Invoking: winAVR Linker avr-gcc -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega32 -o"Loetst.elf" ./trunk/cmdline.o ./trunk/drveeprom.o ./trunk/drvheat.o ./trunk/drvtemp.o ./trunk/drvtimer.o ./trunk/drvuart.o ./trunk/ioadc.o ./trunk/iotimer.o ./trunk/lcd_driver.o ./trunk/main.o ./trunk/pid.o ./trunk/regulator.o c:/programme/winavr/bin/../lib/gcc/avr/4.1.2/../../../../avr/lib/avr5\li bc.a(floatsisf.o): In function `__floatsisf': (.text.fplib+0x4): multiple definition of `__floatsisf' c:/programme/winavr/bin/../lib/gcc/avr/4.1.2/avr5\libgcc.a(_si_to_sf.o): (.text+0x0): first defined here c:/programme/winavr/bin/../lib/gcc/avr/4.1.2/../../../../avr/lib/avr5\li bc.a(fp_cmp.o): In function `__lesf2': (.text.fplib+0x0): multiple definition of `__ltsf2' c:/programme/winavr/bin/../lib/gcc/avr/4.1.2/avr5\libgcc.a(_lt_sf.o):(.t ext+0x0): first defined here c:/programme/winavr/bin/../lib/gcc/avr/4.1.2/../../../../avr/lib/avr5\li bc.a(fp_cmp.o): In function `__gesf2': (.text.fplib+0x8): multiple definition of `__gtsf2' c:/programme/winavr/bin/../lib/gcc/avr/4.1.2/avr5\libgcc.a(_gt_sf.o):(.t ext+0x0): first defined here make: *** [Loetst.elf] Error 1 Wenn ich folgenden mache funktioniert es. Wo ist denn da der Unterschied ? -lm am Ende der Befehlszeile, klar! Aber warum geht es dann? Wenn ich -lm weglasse, sind die Fehlermeldungen wie oben und dass ich -lm brauche ist mir schon klar. Es schent, dass bei dem ersten Linkeraufruf das -lm nicht gesehen wird? Building target: Loetst.elf Invoking: winAVR Linker avr-gcc -Wl,-u,vfprintf -lprintf_flt -mmcu=atmega32 -o"Loetst.elf" ./trunk/cmdline.o ./trunk/drveeprom.o ./trunk/drvheat.o ./trunk/drvtemp.o ./trunk/drvtimer.o ./trunk/drvuart.o ./trunk/ioadc.o ./trunk/iotimer.o ./trunk/lcd_driver.o ./trunk/main.o ./trunk/pid.o ./trunk/regulator.o -lm Finished building target: Loetst.elf Eine weitere Frage noch noch zu -lm. Wenn ich nur Fließkommarechnungen verwende, ohne printf dazu und die Option -lm weglasse, funktioniert das linken. Die erzeugte Datei ist allerdings größer als mit der Option. Was wird denn dazugelinkt, wenn ich -lm weglasse? Danke für Hinweise. Hajo
Haaaallooooooo..... Keiner zu Haus? Hat da keiner eine Idee zu? Echt bitter. :-( drängel ;-) Hajo
Das erklärt meine zweite Frage, also daß eine Standard-Lib vom GCC dazu gelinkt wird, wenn man -lm wegläßt. Ist jedenfalls mein Verständnis. Meine eigentliche Frage, warum z.B. __floatsisf sogar multiple ist anstatt zu fehlen, dass begreife ich nicht. Passiert mit folgender Anweisung: avr-gcc -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega32... object files Wenn ich folgende mache, dann geht es (-lm jetzt am Ende): avr-gcc -Wl,-u,vfprintf -lprintf_flt -mmcu=atmega32... object files -lm Das begreife ich nicht. Dein Patch für __floatunsisf u.s.w. den habe ich begriffen. Aber mein Problem hängt doch nicht damit zusammen?! Danke Hajo
Ich denke schon - sobald der Floating-Point-Code aus der libgcc kommt, hast du verloren.
Und warum unterscheiden sich die beiden Aufrufe für den Linker? Das kapiere ich nicht. In beiden steht doch -lm drin. Und außerdem ist es doch so, wenn ich die GCC-Lib nehme, fällt der Standard-Krams vom GCC weg? Verstehe echt nix mehr. Hajo
Hatte ich schon wolte ich gerade schreiben. Da viel mir ein, dass ich die Vorversion von WINAVR mit der AVR-LIBC 1.5.1 "gepatcht" hatte. Darum war das Verhalten gleich. Jetzt habe ich die alte Version mit der ausgelieferten AVR-LIBC probiert und dann funktionieren beiden Befehlszeilen für den Linkeraufruf. Nur die Codegröße ist bei -lm am Ende der Befehlszeile kleiner. Wieso wird denn schenbar das .lm hier nicht genutzt? avr-gcc -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega32... object files Klingelingeling Und ich glaube jetzt begreife ich langsam, was da passiert. Wenn er -lm nicht erkennt, nimmt er seine Standardlib. Die wiederum kollidiert mit der dazugelinkten printf_flt. Man muß -lm nutzen, damit auch printf_flt funktioniert. Und das passiert bei der alten WINAVR nicht. Da kollidiert es auch nicht. Kannst Du das so bestätigen? Das muß ich in meinem Alter erstmal begriefen ;-) Hajo
Wieso wird denn scheinbar das -lm hier nicht genutzt? avr-gcc -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega32... object files Habe schon im GCC-Manual nachgelesen aber ich kapiere es nicht. Hajo
Das -lm sollte nach all deinen Objektdateien stehen, nicht davor.
Danke Jörg. Habe ich jetzt verstanden. Mich hat interessiert warum das so ist. Ich bin dann doch fündig geworden in der AVR-LIBC Doku unter "Using the GNU Tools". -lm am Ende, damit der Linker die noch nicht aufgelösten Symbole dann aus libm holt. Ich hoffe ich habe das richtig verstanden. Aber warum wird dann bei der "alten" (Vorgänger) Version von WINAVR der Code größer, wenn ich -lm so angebe wie hier, also nicht am Ende: avr-gcc -Wl,-u,vfprintf -lprintf_flt -lm -mmcu=atmega32... object files Also das -lm wird auch dann "verstanden", führt aber zu größerem Code. Der Linker packt Code dazu, der unnötig ist!? Würde gerne den Linkvorgang genauer verstehen. Wo gibt es Infos? Habe gerade im LD Manual nachgesehen. Da steht es nicht. Danke Hajo. Edit: Habe zu lange "woanders" gelesen und nach Infos gegraben. Da habe ich Andreas sein yep übersehen. Auch Dir natürlich ein "danke schön".
Es gibt zwei Floating-Point-Libs. Eine kleine in der libm und eine erheblich grössere und unerwünschte in der libgcc. Das gilt soweit für beide Versionen von WinAVR. Ohne libm oder mit libm vorneweg erwischst du die Version aus der libgcc, was erstens Platz kostet, zweitens in Verbindung mit printf zu Konflikten führen kann. In der aktuellen Version besteht das Risiko, dass man auch bei korrekter Plazierung von -lm Teile aus der libgcc erwischt, weil in der libm etwas fehlt. Das kann dann auch zu Fehlermeldungen bzgl. Doppeldefinition führen. In der Vorversion passiert das nicht, da fehlt nichts.
Oh man, ich werd doch noch schlau ;-) Danke nochmal für die ausführliche Erklärung Andreas. Das habe ich verstanden, soweit hatte ich dann auch schon vermutet. Wenn mir das aber einer bestätigt, dann freue ich mich. Was mir aber noch nicht klar ist, warum erwischt man bei einem -lm vorweg die libgcc? Ich meine -lprintf_flt steht ja auch vorneweg. Das ist dann wieder richtig. Sorry wenn es nervt. Aber ich möchte das einfach verstehen. Eben hat mir Tante Google schon einen schönen Link gegeben: "Beginner's Guide to Linkers". Und es wird der LD behandelt. Da werde ich dann mal lesen. Aber vielleicht hat ja noch einer Lust mir meine Frage oben noch zu beantworten. Danke Hajo
Ha Jo wrote: > Was mir aber noch nicht klar ist, warum erwischt man bei einem -lm > vorweg die libgcc? Weil der Linker hübsch der Reihe nach vorgeht. Wenn -lm vor der Verwendung von Fliesskommafunktionen angegeben wird, dann wird von der libm zu diesem Zeitpunkts nichts benötigt, folglich nicht eingebunden, sie also effektiv ignoriert. Ganz hinten folgt dann (versteckt) die libgcc...
Andreas Kaiser wrote: > Weil der Linker hübsch der Reihe nach vorgeht. Stur wie ein Beamter. Oh je! > Wenn -lm vor der > Verwendung von Fliesskommafunktionen angegeben wird, dann wird von der > libm zu diesem Zeitpunkts nichts benötigt, folglich nicht eingebunden, > sie also effektiv ignoriert. Ja das leuchtet mir dann ein. Davon wäre ich jetzt nicht ausgegangen. Ich hätte vermutet, er macht sich von den angegeben Files, egal ob .a oder .o ein "Gesamtbild" und bindet dann die benötigten Teile zusammen. Aber..... so ganz erklärt es nicht, warum -lprintf_flt vorneweg dann richtig ist. libprintf_flt wird zu dem Zeitpunkt wahrschienlich schon benötigt, da irgendjemand verstecktes danach verlangt?! Das hängt evtl. mit dem -u vfprintf zusammen?? Ich danke Dir schon wieder. Ich weiß Du hast schon mehrere Schubkarren "Danke chön" im Garten stehen ;-) Erstmal gute Nacht jetzt. Hajo PS. Ich träume bestimmt von undefined symbols und suche wie verrückt danach ;-)
In avr-libc 1.6.1 ist die Fliesskomma/String-Konvertierung, die von libprintf_flt verwendet wird, völlig autark und verwendet keine Funktion der Floating-Point-Lib. In avr-libc-1.4.5 jedoch sehr wohl. Der Schlüssel zum Verhalten der Linkers ist "-u vprintf" in dessen Zeile. Damit wird das frühzeitige Laden von vprintf aus der nächsten passenden Lib erzwungen. Das ist hier die libprintf_flt. Ohne -u entstünde das Problem, dass deine Objektfiles möglicherweise nur printf() verwenden, kein vprintf(). printf() ist jedoch nur in der libc drin, verwendet aber seinerseits vprintf(). Das in diesem Fall unweigerlich auch aus der libc käme. Das ist nur zu verhinden, indem vprintf() schon definiert ist.
Hallo Andreas, danke nochmal für die Erklärung. Das hilft dann doch, es zu verstehen. Sind diese Abhängigkeiten eigentlich dokumentiert? Oder muß man, um das herauszufinden, sich den Inhalt der Libs ansehen oder sich sogar den Sourcecode anschauen? Hajo
Ha Jo wrote: > Sind diese Abhängigkeiten eigentlich dokumentiert? Nein. > Oder muß man, um das herauszufinden, sich den Inhalt der Libs ansehen Die Symbolliste. Beispielsweise: avr-nm libprintf_flt.a
Dass man alle printf-Mitglieder auf eine zentrale Funktion (in der Regel eben vfprintf) zurückführt, ist gängige Praxis. Wenn ich mal dazu komme, werde ich mal in die weiteren Bibliotheken die anderen Mitglieder der Familie mit aufnehmen. Dann braucht man den Hack mit -Wl,-uvfprintf nicht mehr. Da Bibliotheken der Auflösung bis dato unbekannter Symbole dienen sollen, gibt man sie immer am Ende auf der Linkerkommadozeile an.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.