mikrocontroller.net

Forum: Compiler & IDEs AVR-GCC Kompiliert nicht benutzte Funktionen mit ein


Autor: Stephan Peterich (sapeterich)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Dieter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Philipp Burch (philipp_burch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
#if 0
//...
#endif
einpacken.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
void foo()
{
   machwas;
}

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
static void foo()
{
   machwas;
}

Dann ist die Funktion jedoch nicht global und nicht in anderen Modulen 
verwendbar.

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Stephan Peterich (sapeterich)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#if 0
//...
#endif
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.
#include "uart.h"
void main(void)
{
 uart_init();
}

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?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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:
int a;
sub1(void) {
  a=1;
}
  
sub2(void) {
  a=2;
}
  
int main(void) {
  sub1();
  return 0;
}

Autor: ANdreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
Program:   81362 bytes (62.1% Full)
(.text + .data + .bootloader)


Mit diesen Optionen:
Program:   66264 bytes (50.6% Full)
(.text + .data + .bootloader)

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.....

Autor: Stephan Peterich (sapeterich)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
??? 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 ^^

Autor: ANdreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erledigt, ist im gesonderten -ld-Handbuch :)

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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....

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@STephan:
Linker-Optionen:
-Wl,--gc-sections

also... MIT dem -Wl

Bringts das vielleicht?

Autor: Stephan Peterich (sapeterich)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab ein neues Projekt angefangen und yalu's Code reinkopiert.
int a;
sub1(void) {
  a=1;
}
  
sub2(void) {
  a=2;
}
  
int main(void) {
  sub1();
  return 0;
}
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.

Autor: Stephan Peterich (sapeterich)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Andreas
Danke für den versuch, aber leider auch nicht :-(

Aber ich gebe das doch an der richtigen Stellen ein?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Andreas Paulin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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...

Autor: Stephan Peterich (sapeterich)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
-ffunctions-sections
 adden
dann [Linker Options] auswählen und die Option
-W1,--gc-sections
 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 :-)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
avr-gcc -mmcu=*** -Wl,-Map,***.map -Wl,--gc-sections  -o ***.elf <o-files>

Ist das elf leer (bzw ist nur .stab und .stabstr drin). Müssen da noch 
weitere Optionen an den Linker? Linkerskript oder so?

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
main() Vergessen?
dann sind alle anderen funktionen unbenutzt und werden rausoptimiert.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: No Name (birger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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"

Autor: Daniel N. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Danke vielmals.
>>Ich dachte ich müsste das W1 als einzelnen Parameter eingeben:
Die Option heisst aber -Wl(ell) nicht -W1(eins).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.