Singularity: Der Wettlauf eines Viewers mit seinem Tod

Der Singularity Viewer hat vor allem in OpenSim noch viele treue Anhänger. Was diese aber zumeist nicht wahrhaben wollen: Der Viewer ist eigentlich mausetot. Oder vielleicht eher untot. Seit 2020 sind keine neuen Binaries mehr herausgekommen. Und es werden auch keine mehr kommen. Der ganze Viewer wird nicht mehr weiterentwickelt werden.

Warum das so ist und warum das so kam, möchte ich hier erzählen.

Singularity ist eigentlich ein uralter Viewer. Vor etwa zehn Jahren wurde er von Ascent geforkt, was seinerseits ein Fork von Inertia war mit dem Ziel, den vor 14 Jahren gestarteten, aber nur kurze Zeit entwickelten Inertia in Second Life zugelassen zu bekommen.

Asbach-Code

So alt der Viewer ist, so alt ist zu erheblichen Teilen natürlich auch der Code. Und wenn man aus der Software-Entwicklung eins gelernt hat, dann ist das: Wenn Bibliotheken oder andere Abhängigkeiten, gegen die etwas entwickelt ist, aktualisiert werden, wird der Code, der gegen sie entwickelt wurde, nicht mitaktualisiert. Jedenfalls nicht, wenn es nicht unbedingt notwendig ist.

Niemand eröffnet einen Issue, weil irgendeine Abhängigkeit aktualisiert wurde, um den Code entsprechend zu modernisieren, wenn der Code auf dem Stand von vor sieben Jahren immer noch wunderbar kompiliert. Und selbst wenn, wird der Issue nicht etwa gefixt, sondern ignoriert oder mit Won't Fix geschlossen. Den Aufwand, etwas zu „reparieren“, was funktioniert, ohne daß sich sichtlich irgendetwas verbessert, macht sich kein Entwickler. Selbst wenn jemand einen Pull Request einreichen würde mit einer gründlichen Code-Modernisierung, dürften viele Kernentwickler keine Lust haben, den zu überprüfen, wenn er nichts wirklich repariert oder verbessert.

Natürlich fängt der Compiler irgendwann an, „Deprecated“-Meldungen auszugeben. Und die werden mit der Zeit immer mehr. Die werden aber geflissentlich ignoriert. Kompiliert ja und läuft hinterher auch. Also alles in Ordnung. „Deprecated“ wird von vielen Entwicklern als „stilistisch veraltet“ angesehen. Tatsächlich aber bedeutet es: „Wird demnächst nicht mehr unterstützt, also kommt in die Puschen und bringt euren Code auf Stand!“

Die ganz schlimmen Finger copy-pasten sogar Code, der deprecated ist, oder schreiben ganz neuen Code, der gleich deprecated ist, weil sie das schon immer so gemacht haben. Außerdem: Wer achtet denn beim Kompilieren darauf, was genau deprecated ist?

Und irgendwann geht’s einfach nicht mehr

Eines schönen Tages dann bekommt man auf seinen Rechner per Systemupdate neue Versionen der Bibliotheken und des anderen Zeugs, gegen die man baut. Auf einmal kompiliert der eigene Code nicht mehr. Was bis gerade eben noch deprecated war, wird jetzt endgültig gar nicht mehr unterstützt.

Dann hat man als Entwickler ein Riesenproblem. Einige Entwickler erinnern sich an die „Deprecated“-Meldungen und sagen: „Hätte ich mal …“ Andere reden sich ein, daß das doch niemand hätte ahnen können, daß das mal passieren würde – nur daß eben die „Deprecated“-Meldungen genau das eben angekündigt hatten.

Gewissenhafte Entwickler würden nun eine sofortige Modernisierung ihres ganzen Code in Angriff nehmen, und zwar mit höchster Priorität. Wenn man allerdings zigtausende oder hunderttausende Codezeilen hat, ist das ein Riesenaufwand, auch ein zeitlicher.

Um trotzdem irgendwas kompilieren zu können, versuchen einige daher, auf irgendeinem Wege alte Versionen ihrer Abhängigkeiten zu installieren. Noch viel mehr Entwickler tun das aber, um die Code-Modernisierung entweder möglichst lange aufzuschieben oder ganz vermeiden zu können. Natürlich bringt auch das nur etwas bei statischen Builds, die die Abhängigkeiten nur zum Kompilieren brauchen und hinterher ohne diese Abhängigkeiten laufen. Ansonsten wäre das Ganze nämlich allmählich auch bei den Nutzern nicht mehr lauffähig.

Irgendwann kommt man dann aber an einen Punkt, an dem die alten Versionen der Abhängigkeiten des eigenen Code auf der eigenen Maschine nicht mehr installierbar sind, weil ihre eigenen Abhängigkeiten nicht mehr da sind bzw. per Update auf eine zu neue Version gebracht werden. Selbst dann gibt’s Entwickler, die schlicht und ergreifend ihre Maschine, auf der sie entwickeln, einfach nicht mehr updaten. Nicht, daß sie sich dann endlich mal dran machen würden, ihren Code auf Stand zu bringen. Natürlich nicht, denn seit aus „deprecated“ „nicht mehr unterstützt“ wurde, hat sich die Menge an eigentlich nicht mehr unterstütztem Code nicht verringert, sondern vermehrt, weil auch der Entwickler sich nicht aufgeschlaut hat, wie man’s denn heute macht.

Paradebeispiel Python

Singularity ging letztlich vermutlich an zwei Abhängigkeiten zugrunde. Die eine ist die GNU Compiler Collection, kurz gcc, die andere Python. Der Python-Anteil im Singularity-Code macht zwar nur 0,6% aus, aber auch die können sich quer stellen.

Schon das ganze Jahrzehnt über gibt es Riesenärger mit uraltem Python-2-Code, von dem irgendetwas abhängt, den auf Python 3 zu bringen aber wie ein unmögliches Unterfangen wirkt. Eigentlich wäre das Migrieren von relativ aktuellem Python-2-Code, also auf dem Stand von Python 2.7, nach Python 3 nicht so überwältigend schwierig. Aber wenn etwas bis heute auf Python 2 basiert, dann basiert es wahrscheinlich auf einer ziemlich alten Version von Python 2, also Python 2.5 oder älter, das noch keine Python-3-Bestandteile hat. Und wieder hat sich niemand je die Mühe gemacht, den Code zu modernisieren, weil er ja auch unter Python 2.7 wunderbar lief. Allen „Deprecated“-Meldungen zum Trotze.

Calibre zum Beispiel, eine E-Book-Verwaltung, ist von 2006, also aus der Zeit von Python 2.5 und somit der Zeit vor Python 3. Python 3.0 war im Dezember 2008 erschienen; zeitgleich kam Python 2.6 raus, das schon Elemente von Python 3 enthielt. Schon im Juni 2009 kamen Python 3.1 und Python 2.7 hinterher. Seitdem wurde aber höchstwahrscheinlich am Bestandscode von Calibre genau gar nichts modernisiert, nicht nach Python 3.1, nicht mal nach Python 2.7.

Auch noch 2008 kündigte die Python Foundation an, die Unterstützung von Python 2 im Jahr 2015 einzustellen. Python-Entwickler hatten sechs Jahre Zeit, ihre Projekte auf Stand zu bringen. Sehr viele haben genau gar nichts gemacht. Anfangs hatten sie keine Eile, dann vergaßen sie es ganz einfach und entwickelten mitunter lustig auf dem vollkommen veralteten Stand von Python 2.5 oder älter weiter, und als der Termin vor der Tür stand, hätte die Zeit nicht mehr gereicht. Das betraf durchaus wichtige, kritische Sachen, auf die nicht verzichtet werden konnte. Also wurde der Support von Python 2 bis 2020 verlängert. Dann sollte aber Ende sein.

Einige drückten nun auf die Tube. Spätestens ab 2018 saßen ihnen einige Linux-Distributionen im Nacken, die sagten, wenn sie nicht auf Python 3 gehen, fliegen ihre Projekte raus.

Schließlich fingen 2020 Linux-Distributionen an, das ab Jahreswechsel 2019/2020 offiziell nicht mehr unterstützte Python 2 aus ihren Softwarequellen zu entfernen. Damit mußten natürlich auch diejenigen Pakete aus den Quellen geworfen werden, die von Python 2 abhingen. Die Entwickler wurden angeschrieben; sie sollten entweder ihre Sachen schleunigst auf Python 3 bringen, oder die werden aus den Quellen entfernt. Einige reagierten wieder erst, als große Distributionen ankündigten, ihre Kreationen aus Versionen mit Langzeitunterstützung (Debian stable, Ubuntu LTS etc.) zu entfernen.

Das betraf letztlich nur noch sehr wenige Projekte. Aber Calibre betraf es sehr wohl. Der einzige Entwickler fing daraufhin an zu jammern, daß Calibre über eine halbe Million Codezeilen auf Python-2-Stand hatte, die könne er nie und nimmer auf Python 3 bringen. Das klang schon sehr danach, als wenn das ganze Ding tatsächlich immer noch praktisch komplett auf Python-2.5-Stand war, also genau überhaupt nichts aus Python 3 eingebaut hatte. Und der Entwickler schlug vor, er könne statt dessen die Weiterentwicklung von Python 2 übernehmen, dann könnten die Distributionen das weiter in ihren Quellen behalten, und er bräuchte Calibre nicht aufwendig zu sanieren. Das schien ihm wirklich der geringere Aufwand zu sein. Allerdings lehnten die Distributionen das ab.

Letztlich konnte Calibre nur weiter bestehen, indem es bis September 2020 doch noch auf Python 3 aktualisiert wurde. Daran wirkten wohl einige Freiwillige mit. Außerdem wurden in diesem Zuge den Entwicklern von Plugins, die immer noch auf Python 2 aufbauten, Pistolen auf die Brüste gesetzt: Wenn die nicht auch auf Python 3 aktualisieren, fliegen ihre Plugins raus. Einige Plugins, die schon längst nicht mehr weiterentwickelt wurden, sind wohl tatsächlich geflogen.

Auch wenn bei Singularity nun der gesamte Python-Anteil auf dem Stand von Python 2.5 sein, also keinerlei Spuren von Python 3 enthalten sollte, ist Python längst nicht das größte Hindernis. Das ist vielmehr gcc, denn Singularity ist größtenteils in C++ geschrieben.

Extremfall gcc

Auch C++ ist nicht TeX, wo 46 Jahre alter Dokumentencode heute noch kompiliert und das daraus resultierende Dokument haargenau so aussieht, wie wenn es vor 46 Jahren kompiliert worden wäre. Es ist auch nicht LaTeX, wo das mit einer Zeitdifferenz von 40 Jahren noch funktioniert. C++ entwickelt sich nicht nur weiter, es baut auch mal Sachen um und schmeißt alte Sachen raus.

Das heißt: Knapp vier Jahrzehnte alter C++-Code kompiliert heutzutage nicht mehr unbedingt. Und schon zehn Jahre alter Code kompiliert heute nicht mehr, wenn er nur ausgefuchst genug ist.

Genau deshalb gibt es ja „Deprecated“-Meldungen. Kaum ein Entwickler folgt irgendeiner Mailinglist, die Änderungen in Compilern ankündigt. Aber was beim Kompilieren passiert, das sehen die meisten. Also wird genau da darauf hingewiesen, daß Teile des Code so veraltet sind, daß das schon kritisch wird und schleunigst behoben werden sollte. Blöderweise ignorieren Entwickler meistens kleinere Mengen an „Deprecated“-Meldungen als harmlos und zu vernachlässigen. Und wenn die Meldungen sich häufen, wird es ihnen zuviel Arbeit, endlich was dagegen zu machen.

Durch sein Inertia-Erbe ist der Code von Singularity zu erheblichen Teilen auf dem Stand von Mitte der 2000er, also bestenfalls dem von C​+​+​03. Auch dieser Code wurde nie auf einen neueren Stand gebracht.

Der C++-Compiler in der Collection heißt g++. Mit g++ 4 war der Code noch kompilierbar, wobei wahrscheinlich neuere Versionen jede Menge „Deprecated“-Meldungen ausgaben. Aber schon der g++ 5 konnte den Code nicht mehr in etwas Ausführbares umsetzen.

gcc 5 kam schon im April 2015 raus, aber Singularity wurde auf einem Ubuntu-LTS-Rechner kompiliert. Ubuntu 14.04 LTS „Trusty Tahr“ kam noch mit gcc 4.8.2. Mit dem Upgrade auf Ubuntu 16.04 LTS „Xenial Xerus“ wurde das aber ersetzt durch gcc 5.3.1. Und schon war Singularity nicht mehr kompilierbar. Das war schon vor gut neun Jahren.

Statt jetzt aber den veralteten Code auf Vordermann zu bringen, ging man einen einfacheren Weg – und bastelte irgendwie wieder gcc 4 auf die Maschine drauf. Aber nicht, um sich für die Code-Modernisierung die nötige Zeit zu verschaffen, sondern wohl eher in der Hoffnung, damit den Code überhaupt nie modernisieren zu müssen. Dahinter stand auch die Hoffnung, daß es bis in alle Ewigkeit möglich sein würde, gcc 4 unter Ubuntu zu installieren.

Nichts geht mehr

Ziemlich genau vier Jahre später wurde Singularity das letzte Mal erfolgreich kompiliert, und zwar immer noch unter demselben alten Ubuntu „Xenial“. Das war im Frühjahr 2020. Inzwischen waren Ubuntu 18.04 LTS „Bionic Beaver“ und Ubuntu 20.04 LTS „Focal Fossa“ erschienen. Es dürfte klar sein, warum der Rechner, auf dem Singularity kompiliert wurde, nicht auf eine der beiden Versionen upgegradet wurde. Vielleicht hatte man festgestellt, daß die alten gcc-4-Pakete schon unter „Bionic“ nicht mehr installierbar waren.

Normalerweise hätte spätestens 2018 die Aussicht, daß gcc 4 irgendwann nicht mal mehr nachinstalliert werden kann, auch nicht aus losen Paketdateien, der Tritt in den Hintern sein müssen, der dazu hätte führen müssen, den Code von Singularity endlich auf einen Stand zu bringen, der nicht schon seit mindestens drei Jahren völlig veraltet war. Passiert ist aber wieder genau gar nichts. Man hatte ja Ubuntu „Xenial“, das lief, da war gcc 4 installiert, Singularity kompilierte, alles war gut.

Wie gesagt, bis Frühjahr 2020. Da wurde noch einmal eine neue Release-Versionen kompiliert, 1.8.9, die erstmals Bakes-on-Mesh neue Beta-Versionen kompiliert. Etwas später folgten ein paar neue Beta-Versionen. Wahrscheinlich ist dann irgendwas mit dem Rechner passiert, auf dem kompiliert wurde. Zu diesem Zeitpunkt dürfte das der einzige noch verfügbare Rechner mit Ubuntu „Xenial“ gewesen sein, auf dem also gcc 4 installierbar war.

Aktuell war damals ja Ubuntu „Focal“, das gcc 9.3.0 mitbrachte und als erstes Ubuntu LTS kein Python 2 mehr. Der Support für Ubuntu „Xenial“ lief noch bis April 2021, aber ich glaube nicht, daß Ubuntu für diese alte Version noch Images zum Installieren zur Verfügung stellte. Hätte also der Rechner, auf dem Singularity kompiliert wurde, neu aufgesetzt oder durch eine andere Maschine ersetzt werden müssen, hätte kein Ubuntu mehr installiert werden können, mit dem Singularity hätte kompiliert werden können.

Ein mögliches Szenario ist also, daß irgendetwas mit dem Entwicklungsrechner bzw. dem Rechner, auf dem kompiliert wurde, passierte. Irgendetwas, das die Weiterverwendung der alten Ubuntu-Installation unmöglich machte, z. B., daß die Festplatte ihren Geist aufgab.

Wie auch immer: Der Rechner stand so, wie er war, nicht mehr zur Verfügung. Es brauchte Ersatz. Dieser Ersatz hätte aber Ubuntu „Xenial“ von 2016 als System gebraucht. Schon 2020 hätte man das Problem gehabt, daß man „Xenial“ nicht mehr hätte installieren können, sofern man kein entsprechend altes Installationsmedium mehr hatte und auch kein ISO-Image, um eins zu bauen. Und wer bewahrt so etwas auf? Schlimmstenfalls hatte man auch die gcc-4-Pakete verloren oder verschlampt und konnte die auch nirgendwo mehr herunterladen, weil Ubuntu „Trusty“, von dem sie kamen, seit 2019 nicht mehr unterstützt wurde.

So hatte man keinen Rechner mehr, auf dem Singularity hätte kompiliert werden können. Man hatte auch keine Möglichkeit mehr, einen Rechner aufzusetzen, mit dem man Singularity hätte kompilieren können. Schon die eh notwendige Weiterentwicklung, um mit Neuerungen in und neuen Anforderungen von Second Life Schritt zu halten, schaffte man 2020 gerade noch so mit Ach und Krach. Selbst die Website war damals schon in Teilen veraltet; das Versprechen, die Singularity-Erklärseite auf den damals aktuellen Stand von Version 1.8.9 zu bringen, wurde nie eingelöst; sie ist bis heute auf dem Stand von Singularity 1.7.0. Da war also auch nicht daran zu denken, den Code von Singularity so aufzufrischen, daß er wieder kompilierbar wäre.

Heutiger Stand

Inzwischen ist 2024. Die letzte Ubuntu-Version, auf der Singularity hätte kompiliert werden können, kam vor zehn Jahren heraus und wird seit fünf Jahren nicht mehr unterstützt. Auch andere Linux-Distributionen unterstützen gcc 4 schon lange nicht mehr. Und selbst die aktuellsten Singularity-Binaries starten, obwohl sie weitgehend statische Builds ohne großartige Abhängigkeiten sind, unter mehr und mehr Linux-Distributionen inzwischen überhaupt nicht mehr.

Vielleicht hätte man noch eine Chance, Singularity unter Arch Linux oder einem seiner Derivate zu kompilieren, ohne den Code anfassen zu müssen. Im Arch User Repository gibt es sehr viele Sachen auch noch in wirklich uralten Versionen, so auch gcc 4.9 und Python 2.7.18. Aber das wäre wirklich für sehr weit Fortgeschrittene – und der Sprung von Ubuntu nach Arch wäre heftig – und würde auf eigene Gefahr laufen, weil beides von den jeweiligen Anbietern schon ewig nicht mehr unterstützt wird.

An eine Weiterentwicklung von Singularity wäre aber selbst dann nicht zu denken. Inzwischen ist sehr viel passiert. Singularity unterstützt noch Windlight, das inzwischen nicht nur in Second Life, sondern auch fast im gesamten Hypergrid durch EEP ersetzt wurde; das wiederum unterstützt Singularity noch nicht. Von Physically-Based Rendering will ich gar nicht erst anfangen.

Es wäre allerdings reiner Wahnsinn, das in den Singularity einbauen zu wollen, wie er jetzt ist. Schon vor acht Jahren ging der Code von Singularity nur noch mit Tricks und unter Verwendung eines veralteten Compilers zu kompilieren. Wenn überhaupt, muß der ganze Code als allererstes um mehr als ein Jahrzehnt modernisiert werden. Ansonsten wäre der Einbau neuer Features wie ein nagelneuer Anbau an einem Gebäude, das seit acht Jahren wegen Baufälligkeit gesperrt ist.

#OpenSim #SecondLife #FürFortgeschrittene #Software