Liebe GCC-Spezialisten, ich erstelle ein Programm in C mit GCC und möchte jetzt gerne den unbenutzten Code durch den GCC rauschmeißen lassen. Dazu nehme ich nach WEB-Anleitung den Compilerswitch CFLAGS += -ffunction-sections hinzu, der mir die functions jeweils in eine eigene Section packt. Das klappt, denn wenn ich das ohne Rauschmeissen zusammenlinke gehts. Dann sage ich dem Linker mit LDFLAGS = -Wl,-Map=$(TARGET).map,-gc-sections,--cref LDFLAGS += $(EXTMEMOPTS) LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) dass er die unbenutzten Sections rausschmeissen soll. Das scheint auch zu klappen, das .elf File ist kleiner. Der Umbau des .elf Files zum ladbaren .hex file gelingt aber nicht, das .hex file wird dann sehr kurz, 13 Byte. Die commandline lautet dazu: avr-objcopy -O ihex -R .eeprom main.elf main.hex Was mache ich denn da falsch? THX Cheers Detlef
Zu wenig Information, daher nur Gestocher: text.* oder text* im Linker-Skript? Entry im Linker-Skript gesetzt? Nur von der Hardware "direkt" aufgerufenen Code (Interrupt-Handler und/oder Vector-Tabelle(n)) per KEEP im Linker-Skript vor unused-code-removal geschützt? Minimale Beispielanwendung mit allen notwendigen Dateien und Beschreibung, wie das Problem nachzuvollziehen ist erzeugen, zusammenpacken und als Attachment hier einstellen.
Hallo, die Antwort auf die Frage wie man den avr-gcc dazu bringt unbenutzte Funktionen rauszuschmeissen würde mich auch interessieren. Suchen - und ich bin eigentlich ein fleissiger Sucher - hat mich bisher nicht weiter gebracht (sorry). Ich verstehe dass auch nicht so ganz, warum macht ein optimierender Compiler die einfachste Optimierung nicht automatisch selber? Ciao, Olli PS: Ich gebe zu ein Windowsuser zu sein, Dinge wie Linkerskripte oder make-Files lösen bei mir keine Begeisterung aus. Ich benutze WinAvr + AVR-Studio. Beispiel C-Program ist einfach: Standard includes, zwei Funktionen definieren, im main nur eine davon aufrufen. Das .lst File zeigt Code für beide Funktionen an, und das .hex File ist auch grösser als wenn man die unbenutze Funktion per Hand auskommentiert.
OlliW schrieb: > Suchen - und ich bin eigentlich ein fleissiger Sucher - hat mich bisher > nicht weiter gebracht (sorry). Ich verstehe dass auch nicht so ganz, > warum macht ein optimierender Compiler die einfachste Optimierung nicht > automatisch selber? Weil das keine Sache des Compilers ist, sondern des Linkers. Der Compiler kennt nur im Ausnahmefall das komplette Programm. Aber abgesehen davon, sieht er immer nur Bruchstücke. Wenn er eine Funktion vorgeworfen bekommt, weiß er nicht, wo diese Funktion überall verwendet wird, es könnte ja auch in einem ganz anderen *.c ein Aufruf dieser Funktion stehen.
Das Beste ist immer noch, wenn man seinen Code selber von "Hand" ausmistet und den nicht benötigten Müll rauswirft! Nur so bleiben Projekte überschaubar bzw. man behält als Programmierer den Überblick! Ausnahme: Wenn man seine eigene Funktionssammlung als "Lib" übersetzt, pickt sich der Linker nur die wirklich benötigten Funktionen raus!
>Weil das keine Sache des Compilers ist, sondern des Linkers.
OK, da war ich schlampig, also neuer Versuch: Ich verstehe dass auch
nicht so ganz, warum wird ein optimierender Compiler mit einem Linker
verpackt der die einfachste Optimierung nicht automatisch selber macht?
:-)
@Peter: das ist Ansichtssache. Ich programmiere sonst mit VisualC und
finde es sehr angenehm dass der mir meinen "Müll" rauswirft :-)
Olli
Müll rauswerfen und total optimieren: --combine -fwhole-program Peter
>ich erstelle ein Programm in C mit GCC und möchte jetzt gerne den >unbenutzten Code durch den GCC rauschmeißen lassen. Unbenutzten Code schmeißt man nicht rau, man schreibt ihn erst gar nicht erst rein. :)
Peter Dannegger schrieb: > Müll rauswerfen und total optimieren: > > --combine > -fwhole-program > > > Peter Ja, aber vergiss nicht zu sagen, dass dann alle .c Dateien in einem Compileraufruf kompiliert werden müssen.
Thomas schrieb: >>ich erstelle ein Programm in C mit GCC und möchte jetzt gerne den >>unbenutzten Code durch den GCC rauschmeißen lassen. > Unbenutzten Code schmeißt man nicht raus, man schreibt ihn erst gar > nicht erst rein. :) :-) Wenn man Code-Baugruppen nicht in Form einer Library benutzt, ist es unausweichlich entweder Funktionen zu haben, die nie benutzt werden oder den Code mit #ifdef zu spicken, so dass sich der Benutzer aussuchen kann, was davon mitcompiliert wird und was nicht. oder sonst irgendeinen Compile/Linker spezifischen Hack gibt, mit dem man das Problem lösen kann. Ein reiner C-Linker kann noch nicht aufgerufene Funktionen detektieren und rausschmeissen, weil es auf jeden Fall eine Referenz auf die Funktion irgendwo geben muss. Für C++ Kombi-Linker ist das allerdings schwieriger bis unmöglich (Stichwort: virtuelle Funktionen).
OlliW schrieb: >... > PS: Ich gebe zu ein Windowsuser zu sein, Dinge wie Linkerskripte oder > make-Files lösen bei mir keine Begeisterung aus. Ich benutze WinAvr + > AVR-Studio. Beispiel C-Program ist einfach: Standard includes, zwei > Funktionen definieren, im main nur eine davon aufrufen. Das .lst File > zeigt Code für beide Funktionen an, und das .hex File ist auch grösser > als wenn man die unbenutze Funktion per Hand auskommentiert. Dann halt das AVR-Studio Projekt mit allen Dateien zusammenpacken und hier anhängen. Das von AVR-Studio erzeugte makefile drin lassen (per default im UVZ default, dann können auch nicht-MS-Windows nutzer "mitraten"). Zumindest mit neueren gcc aus neueren WinAVR keine Probleme mit function-sections/gc-section gehabt, auch in Kombination mit AVR-Studio.
Mit function-sections/gc-section funktioniert das jetzt. War auch schon mal in Beitrag "AVR-GCC Kompiliert nicht benutzte Funktionen mit ein" breit dargestellt, hab ich erst später gesehen. Problem war Version des gcc, ich war bei 3.4 ;-( , mit dem neuen gings. >>--combine >>-fwhole-program Da muß man jedesmal alles compilieren ?! Das kann dauern. >>ich erstelle ein Programm in C mit GCC und möchte jetzt gerne den >>unbenutzten Code durch den GCC rauschmeißen lassen. >Unbenutzten Code schmeißt man nicht rau, man schreibt ihn erst gar nicht >erst rein. :) Super Idee, wäre ich nicht drauf gekommen, es ist immer eine Bereicherung, wenn ein erfahrener Entwickler so helfen kann. THX2ALL Cheers Detlef
ha, jetzt habe ich extra ein Beispiel zusammengestellt und schon gibt es die Lösung... wenn das nur immer so ginge das alleine die Möglichkeit dass ein Beispiel gepostet wird ausreicht um zu einer Lösung zu kommen... ist ja fast quantenmechanisch... ne, echt SUPER, Danke Martin und Detlef!! Und bei meinen Beispiel werden es statt 568 (alle Funktionen) und 216 bytes (nur die benutzte Funktion) mit dieser Lösung am Ende sogar nur 96 bytes (egal mit oder ohne unbenutze Funktionen)! Olli PS: eigentlich gehört soetwas doch in ein gcc-Tutorial mit und GANZ oben rein... PSS: und warum macht der avr-gcc das jetzt nochmal nicht automatisch von selbst? ne, Scherz... echt cool :-)
>Und bei meinen Beispiel werden es statt 568 (alle Funktionen) und 216 >bytes (nur die benutzte Funktion) mit dieser Lösung am Ende sogar nur 96 >bytes (egal mit oder ohne unbenutze Funktionen)! Ob das Programm jetzt aber noch das tut, was es soll? Und auf die Gefahr hin, etwas zu wiederholen: >Unbenutzten Code schmeißt man nicht rau, man schreibt ihn erst gar nicht >erst rein. :) Funktionssammlungen, bei denen man nicht genau weiß, was davon alles benutzt wird, packt man halt in eine lib. Wurde die richtig gebaut, holt sich der linker daraus nur das, was benötigt wird. Ganz automatisch, ohne zusätzliche Optionen. Oliver
Oliver schrieb: > Funktionssammlungen, bei denen man nicht genau weiß, was davon alles > benutzt wird, packt man halt in eine lib. Wurde die richtig gebaut, holt > sich der linker daraus nur das, was benötigt wird. Ganz automatisch, > ohne zusätzliche Optionen. Da eine library aber auch nur eine Dateisammlung ist, hast Du genau das selbe Problem. Der Compiler erzeugt ELF sections für Code und Daten. Alle Funktionen (Code) einer compilation unit landen in der selben ELF section. Der Linker kann eine section nun einbinden oder weglassen. Existiert auch nur eine Referenz auf eine einzige Funktion in dieser section, dann muss diese komplett in das image übernommen werden. Um das zu vermeiden, kannst Du den Compiler anweisen, jede Funktion in seine eigene ELF section zu legen (siehe weiter oben im Thread). Nachteil: Einige Optimierungen können vom Compiler nicht mehr durchgeführt werden. Außerdem vergrößert sich die Menge der Verwaltungsdaten (section table) im ELF image möglicherweise erheblich, was aber bei MCU Anwendungen ohne ELF loader nicht so eine große Rolle spielt. Gruß Marcus http://www.doulos.com/arm/
>Alle Funktionen (Code) einer compilation unit landen in der >selben ELF section. Richtig. Daher mein Zusatz: >Wurde die richtig gebaut,... Eine lib sollte man natürlich aus mehreren sinnvoll zusammengestellten compilation units zusammenbasteln. Oliver
> Eine lib sollte man natürlich aus mehreren sinnvoll zusammengestellten > compilation units zusammenbasteln. Beim Linken von strukturierten Libraries bin ich bisher auch auf keinerlei Probleme "ala jetzt geht das Programm nicht mehr" gestossen. D.h. alle Funktionen die sich bedingen in ein gemeinsames C-File packen, wenn es zu unübersichtlich wird, dann die Funktionen vereinzeln. Das ganze als Library zusammenfassen und zum Main-Programm Linken. Das funktioniert soweit ich weiss auch beim IAR. Vorteil ist, es sind keine abenteuerlichen Compilerschalter im Spiel und man kann damit auch prima Default-Callback-Funktionen handhaben. Wenn der Nutzer sie definiert hat, dann wird das Object-File aus der Library gar nicht erst gelinkt.
@Oliver Oliver schrieb: > Richtig. Daher mein Zusatz: >>Wurde die richtig gebaut,... Peter schrieb: > Ausnahme: Wenn man seine eigene Funktionssammlung als "Lib" übersetzt, > pickt sich der Linker nur die wirklich benötigten Funktionen raus! Es konnte beim Leser der Eindruck entstehen, dass der Linker eine (statische) Library grundsätzlich anders behandelt als einzelne Objekte. Wir wissen, das das nicht der Fall ist. Ich hätte also eher Peter antworten sollen, als Dir. Gruß Marcus http://www.doulos.com/arm/
Peter Dannegger schrieb: > Müll rauswerfen und total optimieren: > > --combine > -fwhole-program Simon K. schrieb: > Ja, aber vergiss nicht zu sagen, dass dann alle .c Dateien in einem > Compileraufruf kompiliert werden müssen. Ich möchte das Thema hier noch einmal aufnehmen. Trotz "compile all" erhalte ich dutzende Fehlermeldungen undefined reference to function... Hat jemand einen Tip woran das liegen kann. Ich nutze WinAVR-20080610 und das AVR Studio (dort habe ich auch die Compileroptionen hinzugefügt)
maxim schrieb: > Hat jemand einen Tip woran das liegen kann. Daran, dass du dich nicht an das hier hältst: > alle .c Dateien in einem > Compileraufruf kompiliert werden müssen. Oder benutzt du etwa ein eigenes Makefile?
Stefan Ernst schrieb: > Daran, dass du dich nicht an das hier hältst: >> alle .c Dateien in einem >> Compileraufruf kompiliert werden müssen. maxim schrieb: > Trotz "compile all" > erhalte ich dutzende Fehlermeldungen undefined reference to function... Ich gehe davon aus, dass mit compile all diese getan wird. Wenn nicht, dann sagt mir bitte was ich sonst machen muss
maxim schrieb: > Ich gehe davon aus, dass mit compile all diese getan wird. Damit wird vielleicht alles übersetzt, aber nicht mit einem Compileraufruf, sondern mit mehreren separaten Aufrufen. > Wenn nicht, dann sagt mir bitte was ich sonst machen muss Eigenes Makefile verwenden.
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.