Forum: Compiler & IDEs WINAVR: eigene Librarys einbinden, nur mit verwendeten funktionen?


von grooves (Gast)


Lesenswert?

Hallo all,

wie kann man in winavr selbst geschrieben .a librarys einbinden, so das 
nur die aufgerufenen Funktionen im code verwendet werden ?
bei mir wird immer die gesamte Library im code verwendet,
was zu sinnloser programm-flash-verschwendung führt .
Bemerkt habe ich die ganze Sache, indem ich unbenutze Funktionen in der 
Library ausdokumentiert habe, wodurch der Programmcode kleiner geworden 
ist.
Ich dachte eigentlich das der Compiler selber merkt welchen Funktionen 
in der Library nicht verwendet werden und diese dann auch nicht in den 
Programmcode einbindet.
Vielleicht irgendeine Option im makefile ????

Danke im Vorraus,
Micha

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


Lesenswert?

grooves wrote:

> wie kann man in winavr selbst geschrieben .a librarys einbinden, so das
> nur die aufgerufenen Funktionen im code verwendet werden ?

Eine Funktion pro Quelldatei schreiben.  Aus allen Objektdateien dann
eine Bibliothek bauen.  Der Linker hat keine Kennung darüber, was
genau eine ,,Funktion'' sei (welche globalen Daten gehören denn dann
zu dieser Funktion?), er arbeitet auf der Basis globaler Symbole und
von Objektmodulen.  Wenn ein Symbol eines Moduls einer Bibliothek
dazu beiträgt, ein zu diesem Zeitpunkt global undefiniertes Symbol
aufzulösen, dann wird der entsprechende Objektmodul aus der
Bibliothek eingefügt.  Ob der aus einer oder 50 Funktionen oder auch
gar keiner (nur globale Symbole im Datensegment betroffen) besteht,
interessiert ihn dabei nicht.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Du musst die Funktionen sinnvoll in einzelne Sourcedateien unterbringen 
und dann erst die daraus erstellten Objektdateien zur Library 
zusammenfassen. Der Linker kann dann aus der Library die unbenutzten 
Objektdateien weglassen. EineStückelung innerhalb einer Objetdatei ist 
nicht möglich.

von grooves (Gast)


Lesenswert?

Danke für die schnellen Antworten,

ich verstehe, der Linker braucht einfach pro Funktion eine .o 
Objektdatei,
um diese ggf. der "Nichtbenutzung" auch weglassen zu können.
Gibt es denn evtl. ne elegante Lösung, aus einer gesamten .c Datei mit 
vielen Funktionen, pro Funktion eine .o Datei zu erzeugen,
wäre sehr komfortabel als pro Funktion eine .c Datei haben zu müssen.

Danke und Grüße,
Micha

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


Lesenswert?

Ich weiß zwar nicht, was daran ,komfortabel' ist (außer du benutzt
ein krückiges Filesystem mit viel ,,Verschnitt'', FAT vielleicht),
aber außer x-mal compilieren mit #ifdef fällt mir nichts dergleichen
ein.  (Das macht die libgcc.a übrigens so.)

Übrigens ist die Aussage ,bei Nichtbenutzung weglassen' einfach mal
komplett falsch herum: es wird ,bei Benutzung genommen' und bei
Nichtbenutzung einfach ignoriert.

von grooves (Gast)


Lesenswert?

na gut, komfortabel find ich es einfach wenn ich nur "EINE" source-datei 
habe, wo z.B. alle meine util-funktionen drin sind,
die dann auch zu "EINER" util-lib führen,
hat jetzt weniger mit n Filesystem zu tun, sondern nur, aus meine Sicht,
... wie ordne und organisiere ich meine Sourcen.
das mit den #ifdef in der libgcc.a muß ich mir mal anschauen, vielleicht 
ist das ja das was mir vorschwebt.
Ansonsten kann ich auch damit leben, pro Funktion ein source-file zu 
haben,
ist ja noch recht übersichtlich an Funktionen was ich da geschrieben 
habe, :-)))

Also, nochmals Danke,
und Grüße,
Micha

von Marcus M. (marcus67)


Lesenswert?

Eine Möglichkeit gibt es noch:

Mit der Compileroption -ffunction-sections und der Linker Option 
--gc-sections kannst Du Compiler/Linker beibringen, nur die Funktionen 
zu laden die auch verwendet werden - sogar ohne eine Library ganz normal 
beim Linken.

Keine Ahnung ob das auch Nachteile hat - würde mich auch mal 
interessieren.

Gruß, Marcus

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


Lesenswert?

Naja, nicht ganz.  Der Linker lädt erst einmal alles, schmeißt
danach aber alles wieder weg, was global nicht gegenseitig
referenziert ist.

von Axel (Gast)


Lesenswert?

Um auf die Sourcedatei zurueckzukommen, ich hatte ein aehnliches Problem 
zum Dateisplitten seinerzeit mit Kommentarmarken und einem Script 
geloest. Das C-File war in etwa so formatiert:
1
/*+Common:*/
2
#include <...>
3
/*+File: foo.c */
4
void foo()
5
{}
6
/*+File: bar.c */
7
void bar()
8
{}
9
/*+End:*/

Du musst deinem Projekt dann aber das passende Splitter-Script, dass im 
Makefile gerufen wird, mit beilegen. Am besten ist es das Script in 
einer HighLevel Scriptsprache wie Python oder Perl zu schreiben und sich 
nicht auf einen Tool-Zoo aus bash, csplit, gawk, sed, ... einzulassen.

Ciao, Axel

von Simon K. (simon) Benutzerseite


Lesenswert?

Viel einfacher ist es doch mit Präprozessor, aber das steht hier ja auch 
schon als Vorschlag.

von Marcus M. (marcus67)


Lesenswert?

Jörg Wunsch wrote:
> Naja, nicht ganz.  Der Linker lädt erst einmal alles, schmeißt
> danach aber alles wieder weg, was global nicht gegenseitig
> referenziert ist.

Hallo Jörg,
wie auch immer, auf jeden Fall ist es weg :-)

Hat das Verfahren eigentlich irgendwelche echten Nachteile (mal 
abgesehen von einem Haufen Sections) ?

Gruß, Marcus

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


Lesenswert?

Marcus Müller wrote:

> Hat das Verfahren eigentlich irgendwelche echten Nachteile (mal
> abgesehen von einem Haufen Sections) ?

Ja, man muss mit Spezialfällen vorsichtig sein.  Eine Initialisierungs-
funktion in .init3 wird ja beispielsweise nie irgendwoher referenziert,
folglich wird sie der Linker rauskicken, wenn du sie nicht auch noch
als "used" markierst.

Einen wesentlichen Nachteil sehe ich, dass diese Funktionalität zu
schlampiger Programmierung verleiten kann: solange all das, was ich
hingeschrieben habe, auch im fertigen Code landet, werde ich darauf
achten, dass nur das noch da steht, was auch benutzt wird.  Wenn ich
mich drauf verlasse, dass der Linker ,,schon irgendwie aufräumt'',
dann kann sich da schnell Müll ansammeln, von dem man in zwei Jahren
erst umständlich recherchieren muss um festzustellen, dass diese
Funktion ja bereits seit der vorvorhergehenden Version gar nicht mehr
genutzt worden war.  (Das trifft natürlich auf den hier vorgestellten
Fall der Bibliotheken so nicht zu.)

Meines Wissens ist die entsprechende Funktionalität insbesondere im
Hinblick auf C++ in die Toolchain gewandert.  Dort gibt es
Konstellationen, bei denen die logische Überschattung bestimmter
Codeteile (bspw. Konstruktoren) für den Compiler nicht ersichtlich
ist, er deshalb den Code zweimal generiert.  Erst der Linker kann
dann feststellen, dass auch auf globalem Niveau einer von beiden
gar nicht benutzt wird.  Anders als oben hat in diesem Falle aber
der Programmierer gar keine Chance, die Doppelgenerierung zu
vermeiden.

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.