Hallo, ich programmiere schon etwas länger mit C und Atmel. Nun habe ich bei einem neuen Projekt für das ich die Sourcen eines alten Projektes zusammengestrichen (auskommentiert) habe, festgestellt, das die auskommentierten Header-Dateien und deren Funktionen trotzdem weiterhin im Programm bleiben. Erst als ich die c und h Files aus meinem AVR-Studio Projekt gelöst habe wurde das Ergebniss kleiner. Es kann doch nicht sein, das unnötige mit einkompiliert werden. In der Suche habe ich folgendes gefunden, dort wird die Frage aber nicht beantwortet: Beitrag "Re: avr-gcc linker Problem" An compiler Optinen verwende ich den AVR-Studio Standard: -Os -Wall -gdwarf-2 -fsigned-char Gibt es eine Option die dem GCC diese Unart abzugewöhnen, die dem widerspricht was ich zu c gelernt habe. mfg und Dank im voraus Stephan
Was widerspricht dem denn? Alle C-Files, die zum Projekt gehören, werden nunmal compiliert, und da der Compiler alle Sourcen separat übersetzt, ist es ihm auch egal, ob der Inhalt des C-Files gar nicht benötigt wird. Wenn Du nur die Header auskommentierst, die C-Files aber im Projekt belässt, dann werden die selbstverständlich mitübersetzt und erzeugen Code.
Gast
#902198
hm, im Compiler wird ne ganze Menge Aufwand getrieben, um den Code zu optimieren. Aber eine so einfache Möglichkeit, einfach nicht benutzte Codeteile nicht mit zu linken wird nicht ausgenutzt? Das versteh ich nicht, aus welchen Grund macht man das nicht?
Dieter wrote: > hm, im Compiler wird ne ganze Menge Aufwand getrieben, um den Code zu > optimieren. Aber eine so einfache Möglichkeit, einfach nicht benutzte > Codeteile nicht mit zu linken wird nicht ausgenutzt? > Das versteh ich nicht, aus welchen Grund macht man das nicht? Ganz einfach: Normalerweise hat man keinen unbenutzten Code im Programm. Die Funktionen aus den Libraries sind davon ja nicht betroffen, die werden nur dazugelinkt wenn sie wirklich verwendet werden. Wenn du einfach testweise eine ganze Datei von der Kompilierung ausschliessen willst, kannst du ja den ganzen Inhalt in
1 | |
2 | |
3 | |
einpacken.
Dieter wrote: > hm, im Compiler wird ne ganze Menge Aufwand getrieben, um den Code zu > optimieren. Aber eine so einfache Möglichkeit, einfach nicht benutzte > Codeteile nicht mit zu linken wird nicht ausgenutzt? > Das versteh ich nicht, aus welchen Grund macht man das nicht? Woher soll denn der COMPILER das wissen? Er sieht nur
1 | |
2 | |
3 | |
4 | |
Woher soll er bitte wissen, dass die Funktion nicht in einem anderen Modul verwendet wird? Wenn Du sowas haben willst, dann 1) Übersetzte jede Funktion in ein separates Objekt 2) Mach aus den Objekten ne Lib 3) Linke gegen diese Lib 4) Du kannst aber auch sagen
1 | |
2 | |
3 | |
4 | |
Dann ist die Funktion jedoch nicht global und nicht in anderen Modulen verwendbar.
Gast
#902229
Der GCC wäre nicht der GCC, wenn es keine Möglichkeit gäbe, unbenutzte Funktionen wegzuoptimieren ;-). Einfach beim Compiler -ffunction-sections und beim Linker --gq-sections angeben. Damit bereitet der GCC die Objektfiles so auf, dass der Linker Ungenutztes wegoptimieren kann. Evtl. noch das GCC- und Binutils-Manual lesen.
1 | |
2 | |
3 | |
ist doch auch keine Lösung, ich programmiere extra mit vielen .h damit ich einfach Sachen wiederverwenden kann. zum Beispiel bei einer "Treiber" Bilbiothek für den UART braucht mann doch nicht immer alle Funktionen. Und das ganze als 20 .h Dateien definieren, z.B. als Uart_Init.h Uart_Senden.h etc. ist doch ... . Und wenn ich diese alle dann auch extra in einem Lib umwandeln muss, obwohl ich noch mitten am Programmieren bin. Mal am Rande gefragt: Wenn ich bei folgendem Code die uart.h nicht im Project des AVR Studios habe, meckert er "undefindef reference to uart_init" obwohl die Dateien im gleichen Verzeichnis ist und das Verzeichnis auch im Suchpfad ist.
1 | |
2 | |
3 | |
4 | |
5 | |
Und die Compiler Optionen helfen leider auch nicht, aber nach dem Mittag lese ich mir mal die GCC / Binutils Doku durch. Macht einer der käuflichen "Konkurrenz" Compiler das besser?
Gast
#902273
> Und die Compiler Optionen helfen leider auch nicht, aber nach dem > Mittag Mein Fehler: Die Linkeroption muss --gc-sections heißen. Bei mir funktioniert das wie erwartet. In folgendem Programm wird sub2() entfernt, sub1() bleibt drin:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
Gast
#902310
Hochinteressant, endlich sagt einem das mal jemand :-D Danke für die Info. Hab gleich mal mit dem aktuellen Projekt einen Test gemacht. Optimierer -O0 und dann build. Ergebnis: Ohne diese Optionen:
1 | |
2 | |
Mit diesen Optionen:
1 | |
2 | |
Ja, super, das lassen wir dann mal so drin. Wenn sich die Objectfiles dadurch ein wenig aufblähen ist doch wurscht, wenn das Endergebnis stimmt. Hab jetzt nur die Frage: WO im gcc-Manual finde ich Info über die --gc(-functions) Option? Habs nirgends gefunden.....
??? Bin ich zu blöd oder was ??? Also ich habs im AVR Studio bei den Project Options für [All files] das -ffunction-sections und bei [Linker Options] --gc-sections eingefügt. Und genau das Beispiel von yalu kopiert. Und nichts ändert sich, das sub2 bleibt sogar im Map File. Ich verwende AVRStudio 4.14 und WinAVR 20080610 das ganze soll auf einem AT90PWM3B laufen. Die restlichen Optionen sind: -Os -gdwarf2 -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums Die habe ich aber auf Voreistellung gelassen. Ähm aber auf jeden Fall schon einmal vielen Dank für die Hilfe, wenigstens hab ich jetzt den Weg gefunden ;-) Nur liegt da halt noch ein Stein rum ^^
Gast
#902338
Erledigt, ist im gesonderten -ld-Handbuch :)
Gast
#902343
@Stephan: Vielleicht hast Du ja einfach keinen unbenutzten Code? Das wäre aber rauszufinden, wenn Du eine selten benutzte Funktion und ihren Aufruf mal auskommentierst....
Gast
#902345
@STephan: Linker-Optionen: -Wl,--gc-sections also... MIT dem -Wl Bringts das vielleicht?
Hab ein neues Projekt angefangen und yalu's Code reinkopiert.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
Und da ist definitv die sub2 "unnütz". Und in meinem eigenen Programm hab ich alles auskommentiert außer der while schleife die einen Port verändert. Wenn ich die ganzen .c und .h aus dem Projekt im AVRStudio lösche bricht mein Programm von 4968 auf 680 byte ein ohne auch nur eine Programmzeile zu verändern.
@ Andreas Danke für den versuch, aber leider auch nicht :-( Aber ich gebe das doch an der richtigen Stellen ein?
Gast
#902364
Wie Andreas Paulin oben geschrieben hat: Wenn die Linkeroption nicht direkt, sondern über den gcc an den ld übergeben wird, muss die Option -Wl,--gc-sections heißen (-Wl,<opt1>,<opt2>... reicht <opt1>, <opt2> usw. an den Linker weiter). Interessanterweise scheint der gcc --gc-sections auch selbst zu akzeptieren, aber da wird sie anscheinend ignoriert.
Stephan Peterich wrote: > Und das ganze als 20 .h Dateien definieren, z.B. als > Uart_Init.h Uart_Senden.h etc. ist doch ... . Die Headerfiles enthalten doch nur die Deklarationen, nicht die Implementierung. Üblicher Ansatz ist halt bspw. eine Headerdatei für die ganze Bibliothek. Die Bibliothek aber besteht aus einzelnen Modulen, die für sich compiliert und in ein Archiv gesteckt werden, das dann dem Linker mit auf die Reise gegeben wird. Der Linker pickt sich daraus dann nur die Module, die er braucht. Nein, mit AVR-Studio-Bordmitteln kannste sowas knicken. Dessen Makefile-Generator ist nur für sehr einfache Probleme gewappnet, Bibliotheken sind außerhalb seines Radars (und auch außerhalb der Idee hinter Mfile). Dafür sollte man schon wissen, wie man die Bibliothek baut und wie man ein Makefile dafür zimmert -- ist ja keine Atomphysik, sowas zu lernen.
Gast
#902373
@Stephan: Sorry, ich meinte natürlich: Nur den Aufruf auskommentieren, nicht die Funktion selber. Genau diesen Rausschmiss soll der Linker ja für uns erledigen.. Und, ja, wie yalu auch sagte: Das "Wl," ist unabdingbar.
Gast
#902399
@Jörg: Hei, Jörg, ich weiß, Du HASST AVRStudio ;-) Aber ich arbeite mit der Kiste, und Du kannst dort tatsächlich ohne großen Aufwand zusätzliche Optionen für - Compiler allgemein - Compiler filespezifisch - Linker allgemein eingeben. Und des dudd.. ;) Der Knacksus bei Stephan ist afaik, dass er das '-Wl,' vergessen hat...
Danke vielmals. Ich dachte ich müsste das W1 als einzelnen Parameter eingeben: Also nochmal als Anleitung für alle die das Problem auch mal haben. Bei AVR-Studio unter Project -> Configuration Options Im Reiter Custom Options . [All files] auswählen dann die Option
1 | |
adden dann [Linker Options] auswählen und die Option
1 | |
adden. @ Jörg: Danke für die Korrektur, du hast recht das in den Headern nur die Definitionen gehören, mein Problem war ja, das reines hinzufügen zum Project ohne include usw. schon den Speicherverbrauch erhöht hat und da ging halt nur ganze Header Datei oder garnicht. Das zu einer .h mehrer .c gehören hatte ich mir schon beim Einsatz von Subversion angewöhnt, damit die Änderungen übersichtlicher bleiben. Also nochmal Vielen Dank. Eventuell könnte das doch wer mal ins Wiki schreiben. Ich finde das schon ein sehr wichtiges Feature und das grösste Platzeinspaarpotenzial für den Compiler überhaupt. Ich hab während der Entwicklung immer ein paar Funktionsleichen :-)
Andreas Paulin wrote: > Hei, Jörg, ich weiß, Du HASST AVRStudio ;-) Sagen wir so: ich bin zu blöd, es zu benutzen. ;-) Das Teil entspricht absolut nicht dem, was ich mir als intuitive Bedienung vorstelle, da es immer gerade Dinge tut, die nicht meinen Intentionen entsprechen... Außerdem läuft es nun mal nur auf Windows, was ich weder habe noch haben möchte. (Aber ich würde es vermutlich selbst dann nicht benutzen wollen, wenn es multiplattformfähig wäre, zumindest nicht mit dem jetzigen Bedienkonzept.) > Aber ich arbeite mit der Kiste, und Du kannst dort tatsächlich ohne > großen Aufwand zusätzliche Optionen [...] eingeben. Klar, das geht. Echte Bibliotheken kann man damit aber eben nicht bauen, das und nur das war mein Punkt.
Hi, ich hab das mal ausgetestet. Bis zu den o-Files ist alles klar, die Funktionen liegen brav in eigenen Sections. Aber wenn ich linke mit
1 | |
Ist das elf leer (bzw ist nur .stab und .stabstr drin). Müssen da noch weitere Optionen an den Linker? Linkerskript oder so?
main() Vergessen? dann sind alle anderen funktionen unbenutzt und werden rausoptimiert.
Ernst Bachmann wrote: > main() Vergessen? > dann sind alle anderen funktionen unbenutzt und werden rausoptimiert. Nein. Ist ein ganz normales Projekt, das ohne die --gc-sections normal bis zum hex ausgeneriert wird. Und enthält dann auch eine main.
Ein interessanter Beitrag, auch für mich. Ich versuche momentan einen tiny2313 mit seinen dürftigen 2KB Flash noch etwas auszureizen. Mit -Wl,--gc-sections erreiche ich aber leider nichts. Nehme ich allerdings einen 3.x GCC dann ist das Ergebnis ein leeres Hex-File. Scheinbar kennt der 3.x GCC diese Option nicht oder versteht sie anders. Lassse ich -Wl,--gc-sections wie vorher fort, so ist das Hexfile deutlich kleiner als bei einem 4.x GCC. Da frag ich mich, wieso mit jeder neuen GCC bzw. AVR-LIBC die Hexfiles immer größer werden. Hab ich da was übersehen? In die Zukunft geschaut, bedeutet das ja bald das Aus für die kleineren Controller, weil da mit neueren Compilern nichts mehr reinpasst. Was für Abspeckmöglichkeiten gibt's denn noch?
Birger Z. wrote: > Scheinbar kennt der 3.x GCC diese Option nicht oder > versteht sie anders. Da wird das Linker-Script den Trick noch nicht vorgesehen haben, und die als lauter eigene Sections erzeugten Funktionen gehen folglich nicht ins ROM sondern direkt ins Nirvana ein. Der Tiny2313 ist allerding auch ein krasser Fall, weil so ziemlich der einzige Bursche ohne Luft nach oben. Ist zwar ein nettes Teil, aber eben deshalb sehr beschränkt. Der Tiny861 beispielsweise hat auch 20 Pins und weit mehr Luft.
Birger Z. wrote: > Ein interessanter Beitrag, auch für mich. > > Ich versuche momentan einen tiny2313 mit seinen dürftigen 2KB Flash noch > etwas auszureizen. Mit -Wl,--gc-sections erreiche ich aber leider > nichts. Nehme ich allerdings einen 3.x GCC dann ist das Ergebnis ein > leeres Hex-File. Scheinbar kennt der 3.x GCC diese Option nicht oder > versteht sie anders. Ok, dann liegt's bei mir daran, hab ja noch die alten avr-binutils. > Lassse ich -Wl,--gc-sections wie vorher fort, so ist das Hexfile > deutlich kleiner als bei einem 4.x GCC. Da frag ich mich, wieso mit > jeder neuen GCC bzw. AVR-LIBC die Hexfiles immer größer werden. Hab ich > da was übersehen? Aus dem Grund bin ich auch noch nicht auf avr-gcc 4.x umgestiegen. Bei mir ist quer über alle Projekte der Flash-Verbrauch um 5-10% größer als mit avr-gcc 3.4.6 GCC 4.2.2 und GCC 4.3.0 hatte ich mal angetestet. Beitrag "avr-gcc: 3.4.6 contra 4.3.0"
Gast
#904542
>>Danke vielmals. >>Ich dachte ich müsste das W1 als einzelnen Parameter eingeben: Die Option heisst aber -Wl(ell) nicht -W1(eins).
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.