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
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.
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.
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
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.
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
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
Naja, nicht ganz. Der Linker lädt erst einmal alles, schmeißt danach aber alles wieder weg, was global nicht gegenseitig referenziert ist.
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
Viel einfacher ist es doch mit Präprozessor, aber das steht hier ja auch schon als Vorschlag.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.