Forum: Compiler & IDEs WinAVR GCC linkt komplette library


von Andreas M. (schnitzeltony)


Lesenswert?

Hallo GCC Freaks,

ich bin gerade vom Glauben abgefallen:

Habe in einer von mir erstellten Library eine neue Funktion 
implementiert und muss feststellen, dass die Codegröße um die Größe der 
Funktion anschwillt, obwohl ich die Funktion nirgendwo aufgerufen habe. 
Das Design ist klassisch: Prototyp in einer öffentliche Header-Datei und 
Implementierung in einer C-Datei, die nur der Library zugänglich ist. 
Habe dann ein bisschen rum gespielt: Erzeuge ich in der gleichen Library 
für die Funktion eine neue C-Datei, deren Inhalt nur die neue Funktion 
ist, wird wieder die Codegröße erzeugt, die ich ohne die Funktion hatte. 
Es scheint mir so, als ob der Linker nur vollständige Objektdateien 
verarbeiten kann.

Ich arbeite mit

WinAVR-20090313 (WinAVR-20081205 zeigt die gleichen Symptome)
Eclipse Europa Version: 3.3.2
AVR Eclipse Plugin 2.3.1.20081204PRD

Zum Erstellen der Library habe ich den Assistenten (AVR Cross Target 
Static Library) verwendet und dann für die verschiedenen 
Controllertypen, die ich gedenke zu verwenden, Debug bzw. Release 
Konfigurationen eingerichtet.

Ist das eine Bug oder ein feature - oder wie bringe ich dem Linker bei, 
die Library C-Dateien nicht komplett zu linken?

von P. S. (Gast)


Lesenswert?

Wenn der Linker aus der Library alles weg laesst, was nicht aufgerufen 
wird, ist sie leer...

von Andreas M. (schnitzeltony)


Lesenswert?

Sorry: Beim Linker meine ich den, der mir die Applikation bindet (unter 
Einbeziehung der Library).

von Karl H. (kbuchegg)


Lesenswert?

> Es scheint mir so, als ob der Linker nur vollständige Objektdateien
> verarbeiten kann.

Deine Analyse ist richtig.

von Arne (Gast)


Lesenswert?

meinst Du sowas:
http://www.mikrocontroller.net/articles/GCC:_unbenutzte_Funktionen_entfernen 
Ich weiß aber nicht, ob WinAVR das auch kann. Habe es beim GCC noch nie 
benutzt. Nennt sich "selective linking" IIRC.

von Andreas M. (schnitzeltony)


Lesenswert?

Das heißt also, dass ich mir bei der Dateistruktur Gedanken machen muss, 
was später möglicherweise nicht verwendet wird. Puh da muss ich mich 
erst mal sammeln: Das hätte ich nicht erwartet :-O

Und noch ne Frage: Macht das nur der AVR-GCC so oder auch die für andere 
Plattformen (z.B. AVR32)?

von Stefan E. (sternst)


Lesenswert?

Andreas Müller wrote:
> Das heißt also, dass ich mir bei der Dateistruktur Gedanken machen muss,
> was später möglicherweise nicht verwendet wird. Puh da muss ich mich
> erst mal sammeln: Das hätte ich nicht erwartet :-O

Normalerweise packt man bei Libraries einfach jede Funktion in eine 
separate C-Datei. Dazu noch eine weitere Header-Datei für alles 
Lib-interne, und gut is.

von Andreas M. (schnitzeltony)


Lesenswert?

Mein letzter Post war für Karl Heinz

Arne: Ich denke schon, dass ich so was gesucht habe das dumme ist nur, 
dass ich es nicht ans laufen bekomme..

Stefan: Sowas willst Du ernsthaft warten?

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


Lesenswert?

Andreas Müller wrote:

> Stefan: Sowas willst Du ernsthaft warten?

Warum nicht?  Was ist daran tragisch?  Alle gängigen Unix-Bibliotheken
sind in diesem Stil aufgebaut.

von Andreas M. (schnitzeltony)


Lesenswert?

Jörg Wunsch wrote:

> Warum nicht?  Was ist daran tragisch?

Ich finde die Übersichtlichkeit wird nicht unbedingt dadurch gesteigert, 
dass der Compiler mir vorschreibt, keine thematischen Gruppierungen 
vornehmen zu dürfen.

> Alle gängigen Unix-Bibliotheken sind in diesem Stil aufgebaut.

Die sind auch lange gewachsen und C++ gibt's da auch eher selten. Würde 
sich heute jemand daran machen, ist fraglich, ob die dann wieder so 
aussähen.

Wahrscheinlich ist es auch nur Gewohnheit: Ich habe ne Menge Projekte 
unter C++ gemacht. Dort haben sich schon mal gerne einige hundert 
Klassen versammelt (immer brav *.h *.cpp). Hätte ich dort jede Funktion 
in eine eigen Datei räumen müssen (OK da war Speicherbelegung nicht 
wirklich ein Thema) hätte ich sicherlich keine Zeit hier zu posten...

Nur damit ich nicht falsch verstanden werde: Der AVR-GCC ist sehr schön 
und ich versuche nicht, damit C++ Projekte durchzuführen. Ich hätte nur 
gerne die Dinge thematisch gruppiert, um auch morgen noch durch zu 
steigen.

Ich werde mal weiter versuchen, die linker-garbage-collection ans laufen 
zu bringen...

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


Lesenswert?

Andreas Müller wrote:

> Die sind auch lange gewachsen und C++ gibt's da auch eher selten. Würde
> sich heute jemand daran machen, ist fraglich, ob die dann wieder so
> aussähen.

Möglicherweise doch, ja.  Es wachsen ja auch nach wie vor welche
nach. ;-)

C++ ist meines Wissens der Hauptgrund, warum -gc-sections überhaupt
voran getrieben worden ist: dort entstehen teilweise implizite
Gebilde, die man sonst nicht vernünftig wieder los wird.

von Karl H. (kbuchegg)


Lesenswert?

Wenn du mal genauer drüber nachdenkst, ist es für den Linker gar nicht 
so einfach festzustellen, ob eine Funktion benötigt wird oder nicht.
1
typedef void (*func)();
2
3
void foo1()
4
{
5
}
6
7
void foo2()
8
{
9
}
10
11
int main()
12
{
13
  func ptr;
14
15
  ptr = foo1;
16
  (*ptr)();
17
}

Der Linker (nicht der Compiler) hat keine Chance rauszufinden, dass foo1 
tatsächlich aufgerufen wird und foo2 nicht.
In C++ mit den virtuellen Funktionen wird das Ganze dann noch eine 
Klasse schwieriger.

> Stefan: Sowas willst Du ernsthaft warten?
So schlimm ist es dann auch wieder nicht. Jede Funktion in eine eigene 
*.c ist sicherlich ein Extremfall. Normalerweise hat man ja Funktionen 
die auf jeden Fall zusammen benutzt werden. In einer Liste wird wohl die 
Add, Traverse und Delete Funktion immer gemeinsam benutzt werden, 
wohingegen die Sort Funktion anwendungsabhängig mal dazu kommt und mal 
nicht.

von Andreas M. (schnitzeltony)


Lesenswert?

Karl Heinz,

mir scheint, das Beispiel hat nicht wirklich etwas mit dem Problem zu 
tun: Es geht doch darum, welche 'Granularität' der Linker bei seiner 
Entscheidung verwendet: Object-Datei oder Funktion. Im Falle der 
Object-Datei (default) scheint er dem ja auch ordentlich nachzukommen 
(wohl auch für Dein Beispiel, wenn foo1 und foo2 in unterschiedlichen 
C-Dateien implementiert werden).

Oder liege ich falsch? Ich frage deshalb, weil ich angefangen habe, die 
Struktur den Compiler-Wünschen anzupassen...

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


Lesenswert?

Ein Objektmodul wird aus einer Bibliothek (also aus einer Datei mit
der Endung .a!) dann und genau dann hinzu gezogen, wenn er (mindestens)
ein Symbol definiert, das beim Linken derzeit `external undefined'
ist.  Ob das Symbol dabei eine Funktion (Codereferenz) oder Daten
ist, das gerade nachgefragt wird, spielt keine Rolle.  Damit zieht
sich also letztlich der Modul auch ggf. ,,seine'' Daten noch mit
ins Resultat hinein.

von Andreas M. (schnitzeltony)


Lesenswert?

Einen hab ich noch:

Ich habe meine Libraries umstrukturiert, so dass die Implementierungen 
feiner auf C-Dateien verteilt sind.
Ich muss sagen: Mir fallen die Schuppen von den Haaren (oder wie heißt 
der Spruch): Da optimiere ich tagelang an meinem Code rum mit dem 
Erfolg, wenige Bytes einzusparen, um dann mit kleinem Aufwand bei 
einigen Projekten an die 1000 Bytes zu sparen.

Fazit: Hat nicht weh getan und viel geholfen.

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.