[FreeBSD] Portupgrade - Verstaendnisfrage

lockdoc

Well-Known Member
angenommen ich will libiconv mit portupgrade auf den neuesten Stand bringen.
Das klappt ja auch recht problemlos. Nun habe ich aber in den man-pages zu portupgrade gelesen, dass ich auch via
Code:
portupgrade -r libiconv*
updaten kann. Dass heisst er date auch alle Programme up, die zum kompilieren libiconv benoetigen. Nun zur Frage:

Das recursive portupgrade sollte doch eigentlich standardmaessig benutzt werden, denn was nuetzt mir eine aktuelle libiconv, wenn alle Programme, die dies benoetigen noch mit der alten kompiliert sind. Beispielsweise hat libiconv ein security hole - dann waehren doch alle programme die noch mit dem alten libiconv compiled sind auch betroffen. Also recursive bauen...

Das ist natuerlich wie ich grade feststelle extrem anstrengend, weil man ja fast immer das system komplett neu kompilieren muss.

Nun kommt noch hinzu dass ich eigentlich zusaetzlich auch noch upwards-recursive (-R)
Code:
portupgrade -r -R libiconv*
kompilieren muesste, damit alle Abhaengigkeiten die libiconv benoetigt vorher auch auf den neuesten Stand gebracht werden. Das bedeutet aber quasi durch die ganzen Abhaengigkeiten, das sogut wie immer alles kompiliert werden muss, wenn sich bsp. eine lib aendert.

Wie seht und wie handhabt ihr das?
 
Du hast da einen entscheidenden Denkfehler. Du gehst davon aus, dass ein Programm was auf libiconv oder einer anderen Bibliothek basiert, fest mit dieser verbunden wird. Dem ist aber nicht so. Der Trick heißt "run -time link-editor" oder kurz rtld(1).
Grundsätzlich gibt es zwei Arten ein Programm und seine Bibliotheken zusammenzufügen. Was du annimmst, ist das statische Linken. Dabei setzt der Link Editor ld(1) nach dem Compilen das Programm und die Bibliothek fest und untrennbar zusammen. Statisch halt. Das hat gewisse Vorteile, wie zum Beispiel das das Programm keine oder nur sehr wenige Abhängigkeiten hat. Kommerzielle Programme werden daher meist statisch gelinkt. Da alle Abhängigkeiten eingebaut sind, musst du dich nicht um sie kümmern, du hast keine Probleme sie zu erfüllen. Es hat aber auch gravierende Nachteile. Sehr hoher Speicherplatzverbrauch, jede Bibliothek ist in jedes Programm was sie braucht eingebaut und entsprechend oft auf der Platte vorhanden. Stelle dir mal vor, wenn jedes GTK-Programm GTK fest drin hätte. Das wären etliche Megabytes. Außerdem auch hoher Arbeitsspeicherverbrauch, aber das würde nun zu weit führen.
Daher hat man die andere Methode erfunden, das dynamische Linken. Dabei sieht der ld(1) nach dem Compilen nur vor, was an Bibliotheken gebraucht wird, fügt sie aber nicht ein. Stattdessen vermerkt er nur den Namen der Bibliothek. Wenn du das Programm startest, kommt rtld(1) ins Spiel. Das "rt" steht wie oben gesagt für "run time". Er nimmt dein Programm, schaut nach welche Bibliotheken dort vermerkt sind, lädt sie dynamisch nach und bindet sie ein. Diese dynamisch einzubindenden Bibliotheken enden auf ".so". In der Praxis wird fast immer dynamisch gelinkt. Das führt zu den Abhängigkeiten. Angenommen, dein Programm braucht libiconv.so. Dann kann es nur funktionieren, wenn auf deinem System eine libiconv ist. Daher ist in den Ports eine Abhängigkeit von deinem Programm auf libiconv vermerkt.
Das ganze hat ein paar Vorteile. Einmal, die Speicherplatzersparnis. Aber auch Unabhängigkeit. Dazu gleich mehr. Es hat aber auch einen gravierenden Nachteil. Die Bibliotheken müssen vorhanden sein. Das sicherzustellen, geht praktisch nur mit einem ausgereiften Paketmanament wie den Ports oder Debians dpkg. Microsoft ist mit diesem Problem ziemlich auf die Schnauze geflogen, dass war nämlich die "DLL Hölle" früherer Windows-Versionen. Eine ".dll" ist vom Prinzip her nichts anderes als eine ".so".
Nun zur Unabhängigkeit. Wenn du libiconv nach einer Sicherheitslücke neubaust, erhältst du eine neue libiconv.so ohne die Lücke. Sobald du das Programm was sie nutzt neu startest, wird es vollautomatisch mit dieser neuen libiconv.so verbunden, hat die Lücke also auch nicht mehr. Du musst daher alles, was auf libiconv basiert nur neu starten, aber nicht neu bauen. Ich habe mir daher angewöhnt, nach Portupgrades grundsätzlich einmal aus- und anschließend wieder einzuloggen, um sicher zu sein, dass alles neu gestartet wurde. Wer ganz sicher sein will, startet die ganze Kiste neu oder geht einmal in den Singleuser Mode und wieder zurück.
Problematisch ist nur, wenn sich die Schnittstelle der Bibliothek ändert, so gerade erst am Wochenende geschehen. libjpeg wurde aktualisiert, die neue Bibliothek war mit der alten inkompatibel, da man ihre Schnittstelle geändert hatte. Alte Programme konnten also mit der neuen libjpeg.so nicht mehr verbunden werden. Daher musstest du alles neubauen, was auf libjpeg basierte, damit die Programme die Schnittstelle bekamen. Diese Schnittstellen werden mit einen kleinen Trick sichtbar gemacht:
Code:
lrwxr-xr-x   1 root  wheel        13  6 Feb 09:54 libjpeg.so -> libjpeg.so.11
-rwxr-xr-x   1 root  wheel    244471  6 Feb 09:54 libjpeg.so.11
Bibliotheken bekommen ihre Versionsnummer in den Namen. Sie heißt ".so.11", also elfte Version der Schnittstelle. Man erstellt dann einen Symlink auf diese Datei, der nur auf ".so" endet. Den sehen die Programme. So ist am Namen der Blibiothek sichtbar, was da eigentlich installiert ist. Hättest du nur libjpeg aktualisiert, aber die Programme darauf nicht, hätte er sowas wie "libjpeg.so.10 not found" gesagt und sich beendet, da er eben die Schnittstelle in Version 10 bräuchte, du aber durch das Update Version 11 hast.

EDIT:
Immer wenn sich die Schnittstelle einer Bibliothek ändert, werden inzwischen die Versionsnummern aller Ports, die diese Bibliothek brauchen, erhöht. Dadurch weiß Portupgrade, dass es all diese neu bauen muss und macht es automatisch. Früher tat man das nicht, da musste man dann wirklich mit -r bei.
 
Super Erklärung

Super Erklärung. Als Neueinsteiger hatte ich mich ein wenig über die "Kompilier-Arie" gewundert. So macht das ganze natürlich Sinn.
 
Finde schade, daß Yamagis ausführliche Erklärungen im "Sumpf" des Forums nach einer Weile verloren gehen :) Ab damit ins Wiki?!?! Yamagi erklärt X oder so... Kein Scherz.
 
Zurück
Oben