Hi, mal ne Frage zum Linker. Kann der gnu c linker (speziell beim avr gcc) eigentlich nur statisch linken, also immer nur komplette object files oder holt der sich aus den files nur die funktionen raus die im programm wirklich angesprungen werden? also ich hab zb na math lib mit den funktionen x() y() und z(), das Programm braucht aber nur z(). Wird dann aus der lib "math" nur z() dazugelinkt oder alles? JarJar
Hallo JarJar, das kannst Du leicht ausprobieren - lass ihn doch mal irgendwas dazulinken, was Du garnicht verwendest. Meine Erfahrung ist, dass alles was man zum Linken angibt auch dazugelinkt wird (zumindest bei selbstgeschriebenen Projektteilen). Im Klartext, wenn ich meine LCD-Lib mitlinke und keine einzige Funktion verwende, dann kommt im ObjectCode auch die ganze LCD-Lib vor. Theoretisch kann der Linker herausfinden, was man wirklich braucht und was nicht - in wie fern der Linker bnei avrgcc das macht - keine Ahnung. Wenn jemand Hinweise hat, wie man den Linker dazu erzieht nicht verwendete Funktionalität beim Linken wegzulassen - als her damit. Ich würde mich schon dafür interessieren. Das nur am Rande. Ich habe dazu noch nicht viel recherchiert - als bitte keine RTFMs - sagt einfach, ob's geht oder nicht und schreibt das, was Ihr gerade dazu im Kopf habt.... MfG, Daniel.
Deine Begriffsdefinition ist etwas problematisch. Als dynamisches Linken bezeichnet man es, wenn Bibliotheken zur Laufzeit des Programms ad-hoc nachgeladen werden. Bei Microcontrollern eher unüblich. Zudem ist es grad andersrum als von dir skizziert. Beim dynamischen Linken wird prinzipbedingt stets die komplette Biblilothek geladen. Beim statischen Linken hingegen nur der minimal notwendige Teil ins Programm direkt eingebunden. Was genau diesen Teil ausmacht hängt von der verwendeten Darstellung der Funkionen im Objektfile ab (neuere vor allem im C++-Umfeld entstandene Link-Techniken) und mitunter auch davon, wie fein der Autor der Library die einzelnen Funktionen in einzelne Objektfiles aufgedröselt hat (ältere Link-Techniken, Assembler-Quelltext).
Hm, ok. Wie nennt man das dann wenn der Linker in der Lage ist nur den benötigten Code aus ner Lib zum endgültigen Programm zu linken und kann der AVR GCC das? Bei "größeren" Compilern hab ich das schon gesehen. JarJar
Das nennt man Linken. Oder statisches Linken. Und es wird seit anno Tobak so gemacht. Ich hab's eigentlich fast nie anders gesehen. Blöd ist lediglich, wenn der Autor der Lib zu faul war, die einzelnen Funktionen in seinem Quelltext in einzelne Files aufzudröseln, sondern der Einfachheit halber alle in ein einziges File schmiss. Dann hat mancher Linker wenig Chancen und schnappt sich alles en bloc. Hast Du einen konkreten Anlass für deine Frage? Ich hab das Gefühl Du rennst offene Türen ein.
Hallo A.K. nach Deinen Ausführungen würde man für jede einzelne Funktion eine eigene Datei benötigen. Das kann so nicht sein - ist ja für den Linker auch nicht wirklich ein Problem. Tatsächlich habe ich beim Erstellen von Programmen bemerkt, dass auch wenn eine Lib nur eine Funktion enthält und diese nicht im Programm verwendet wird, der Code sich trotzdem um das Maß dieser Funktion vergrößert (beim Programmerstellen für den µC). Weißt Du (oder jemand anders) nun, ob und wenn wie man den Linker dazu bringen kann, nur die Teile dazuzulinken, die auch wirklich verwendet werden ? MfG, Daniel
Man benötigt für jede Optionale Funktion ein eigenes objectfile, das Später in eine Library eingefügt wird! Beispiele wie 'free' und 'malloc' können dabei wieder in einem objectfile stecken, da sie eh voneinander abhängig sind.
Hab ich noch nicht erlebt. Was ich indes öfter erlebt habe, ist die Frage warum zum Teufel der Linker auf die hirnrissige Idee kommt grad die exotische Funktion einzubinden, die ich garantiert nirgends verwendet habe. Naja. wie üblich stellt sich dann heraus, recht hat er doch. Um ein paar Ecken herum beispielsweise. Oder im Startup-Code. Oder... "nach Deinen Ausführungen würde man für jede einzelne Funktion eine eigene Datei benötigen. Das kann so nicht sein" Weil nicht sein kann was nicht sein darf? Grad so arbeiten traditionelle Linker. Bei denen ist das Objektfile eine unteilbare Einheit. Wie schon gesagt, erst im Umfeld von C++ und Templates hat sich das gezwungenermassen geändert. Was nicht unbedingt heisst, dass GCC/AVR das so macht, nur das es da technisch sicherlich möglich ist (keine Ahnung ob oder ob nicht, ich hab mir das noch nicht angesehen). Guck dir Quelltexte von Standard-C-Libraries an (string.h, math.h und sowas). Üblicherweise für jeden Kleinscheiss ein eigenes File. Warum wohl? "ist ja für den Linker auch nicht wirklich ein Problem." Ach? Wie soll der Linker die Funktionen auseinander halten, wenn sie ihm im Objektfile als geschlossener Block präsentiert werden? Keine Chance. Erst wenn die Compiler/Assembler jede Funktion als eigenständige Einheit im Objektfile unterbringen (muss das Obj-Format freilich erst mal abkönnen), dann geht das.
NB: Ein Freund und ich hatten anno 68000 mal ein eigenes System entwickelt, mit Betriebssystem, C-Compiler, Assembler, Linker usw. Der Compiler stammte von der Uni, der Rest war Eigenbau. Jedenfalls hatte mich just diese Eigenheit von Libraries genauso gestört, weshalb das Objektfile-Format denn auch identisch dem Library-Format war, und Compiler/Assembler bis zu 32 unabhängige Module in einem Quelltext unterbringen konnten. Uns war's einfach zu blöd, wegen jedes einzelnen 5-Zeilers eigens den damals ja von Floppy-Disk gestarteten Compiler anwerfen zu müssen. Diesen Trick (obj=lib) habe ich freilich noch nirgends wiedergefunden, wenngleich ich es bis heute für sinnvoll halte.
Warum wird eigentlich so ne Diskussion draus? Ein simples "Ja" oder "Nein" hätte gereicht. d.h. also wenn ich ne brauchbare und kleine Library von Funktionen erstellen will muß ich alles in möglichst kleine Blocks unterteilen und in einzelnen Object Files speichern. Mal ein Beispiel: Ich schreibe eine Lib für ein Display, da gibts die Funktionen "Init", "Write", "Clear", "Cursor_Pos" und noch einige mehr. All diese Funktionen müsste ich in einzelnen Files abspeichern und der Programmierer müsste manuell bestimmen welche der Funkitonen er in seinem Programm hat? Das ist doch so ineffizient und unkomfortabel wie nur was
Wieso denn bitte Manuell? Das macht ja gerade der Linker für den Programmierer, nicht der Programmierer selbst! Ganz weit hergeholt muss natürlich doch wieder der Programmierer entscheiden, was reinkommt und was nicht, aber das macht er ganz unterbewusst, indem er eine Funktion entweder benutzt, oder eben nicht ;-) Ist Deine Library gut organisiert, und der Programmierer verwendet eine darin enthaltene Funktion nicht (weil er sie nicht braucht), dann kommt sie auch später nicht mit in das ELF... Ich hätte ja schon längst ein Beispiel gebracht, aber dazu fehlt mir grad die Zeit...
Du hast wohl nicht ganz verstanden, wie der Linker arbeitet. "All diese Funktionen müsste ich in einzelnen Files abspeichern ..." Ja, es ist korrekt, daß jede einzelne Funktion in ein eigenes Source- und also Objektfile gehört. Diese werden vom Librarymanager zu einer Library verwurschtelt. "und der Programmierer müsste manuell bestimmen welche der Funkitonen er in seinem Programm hat?" Und nein, der Benutzer der Library muss sich nicht darum kümmern, welche Objektdateien er aus der Library verwendet - das nämlich macht der Linker. Der bestimmt zunächst alle nicht aufgelösten Symbole (beispielsweise aufgerufene Funktionen, bei denen die Implementierung fehlt) und durchsucht dann alle ihm übergebenen Objektdateien und Libraries nach diesen. Wird so ein Symbol in einer Library gefunden, wird die dieses enthaltene Objektdatei aus der Library zum Projekt dazugelinkt. Fertig. Funktioniert wunderbar, ist komfortabel und effizient und seit Jahrzehnten so erprobt. Es gibt allerdings Linker, die -aufgrund eines deutlich komplexeren Objektdateiformates- in der Lage sind, auf Funktionsebene zu linken, das heißt, aus einer Objektdatei nur die verwendeten Teile zu extrahieren. Ein frühes Beispiel dafür war der in Borlands Turbo Pascal integrierte Linker. Natürlich zwingt Dich niemand dazu, auch wirklich alle Funktionen Deiner Library in eigenständigen Source- und also Objektdateien zu organisieren; das bleibt frei Deiner Lust und Laune überlassen. Gutes Librarydesign sieht so eine Arbeitsweise aber vor. Ich sehe auch überhaupt kein Problem darin; es erfordert vom Libraryentwickler nur ein kleines bisschen Selbstdisziplin (sinnvolle Namensvergabe von Source- und Headerfiles, etwas Nachdenken über #include-Strategien), ist danach aber so selbstverständlich wie das Atmen. Selbst wenn nicht eine Library entwickelt wird, lohnt es sich, mit modularen Codeblöcken zu arbeiten. Das steigert unter anderem die Chancen der -Achtung, jetzt kommt ein "buzzword"- Code-Reuse. Beim Arbeiten im Editor ist ein 100 Zeilen langes Sourcefile mit ausschlaggebenden Namen auch übersichtlicher als ein 4000 Zeilen langes ...
...und jetzt hab ichs doch gemacht... Siehe Anhang, entpacken mit 'tar -xvjf linkertest.tar.bz2' im Verzeichnis Deines Vertrauens. Lib erstellen mit: * avr-gcc -c -Os -ggdb -o foo.o foo.c * avr-gcc -c -Os -ggdb -o bar.o bar.c * avr-ar -qcs libfoobar.a foo.o bar.o Inhalte anzeigen: * avr-nm -s libfoobar.a ...für alle Die das mal nachvollziehen wollen. Dann noch 'make clean all' und ins .map-File schauen und nach 'foo.o', welches enthalten ist, und 'bar.o' welches nicht enthalten ist, suchen! Viel Spaß!
Ok, wunderbar, danke für die Erklärung. Leider ist das ganze für mich noch nicht ganz so selbstverständlich wie das Atmen, aber ich würde gerne wissen wie das geht. Gibts es das irgendwo nachzulesen? Ich hab zwar diverse Bücher, meist aber mehr zu C++ und alles für den PC und zu dem Thema schweigen sich alle aus. Vielleicht kann sich ja jemand erbarmen und das Thema hier in dem großen Tutorial anzugehen (wenn's nicht schon drinsteht und ich dösel das blos noch nicht gesehen hab). Die Sprache C ist für mich das kleinere Problem, hab ich auch früher schon programmiert. Allerdings noch zu Borland C 3.1 Zeiten unter DOS. Da hab ich mich um sowas nicht gekümmert. Viel schwieriger ist für mich das ganze "Drumrum" wie makefiles und Linker usw
Hm, naja, vielleicht liest Du mal die Beiträge?
>Dateianhang: linkertest.tar.bz2 (12.4kB, 0 Downloads)
Das war doch jetzt nicht wirklich für die Katz', oder?
:-)
GCC kann mittlerweile selber entscheiden welche Funktionen verwendet werden und welche nicht. CPFLAGS += -ffunction-sections LDFLAGS += -ffunction-sections -Wl,--gc-sections -Wl,-uInterruptVectors ich hoff das war alles was nötig is. Wenn nicht schau ich nochmal nach. Funktioniert zumindest beim MSP430 problemlos.
Selbst wenn das mit WinAVR geht, dann muss freilich die Library so übersetzt werden, nicht bloss das eigene Programm.
Außerdem muss man sich dann wieder mit Krücken wie dem genannten -Wl,-uInterruptVectors behelfen, um all die Symbole, die drin bleiben sollen, zu benennen. Auf jeden Fall heißen die Interruptvektoren bei avr-libc erst einmal anders, außerdem braucht man ähnliche Krücken, um eigene init-Funktionen (in .init3 oder so) nicht rauskicken zu lassen. Ich finde die Methode insgesamt alles andere als elegant. Sie fördert meines Erachtens lediglich die Faulheit des Programmierers, sich um seine Codestruktur noch weniger Gedanken zu machen. Mögen Compiler und Linker dann das Chaos doch richten...
@Jörg: Vielleicht hast Du damit ja gerade den Stein der Erkenntnis gefunden, warum Programme von Microsoft oft so ... sind, wie sie sind.
>Hm, naja, vielleicht liest Du mal die Beiträge?
Den hast du grad gepostet als ich selbst geschrieben hab. Hab ich erst
hinterher gesehen. Eine Beschreibung im Wiki wäre trotzdem nicht
schlecht, wäre dann etwas langlebiger und nützlich für die
Allgemeinheit.
Aber ich werd mir das Beispiel heute oder morgen mal vornehmen
Super, klasse. Das ist endlich mal was womit man was anfangen kann!!! Ich danke recht herzlich Schönes Wochenende JarJar
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.