Ende der Swift-Einführung – Abschluss des Swift-6.0-Support-Issues im Ladybird-Browser
(github.com/LadybirdBrowser)- Das Ladybird-Browserprojekt hat eine Liste von Problemen zusammengestellt, die beim Übergang des Swift-6.0-Supports vom Experiment in den regulären Einsatz auftraten, entschied anschließend jedoch, die Einführung von Swift nicht weiterzuverfolgen
- Die wichtigsten Hürden betrafen die Interop zwischen Swift und C++, darunter ABI-Inkonsistenzen, zirkuläre Header-Abhängigkeiten und die Unmöglichkeit, bestimmte Typen zurückzugeben; mehrere Punkte wurden nach Swift 6.0.0 behoben
- Auch im CMake-Build-System wurden Probleme gemeldet, etwa nicht übereinstimmende Deployment-Targets in Swift-+Ninja-Umgebungen, Fehler bei der
install_name-Verarbeitung und inkompatible Compiler-Optionen - Auch im Ladybird-eigenen Code wurden zahlreiche Build-Instabilitäten festgestellt, darunter die modulemap-Konfiguration der Module AK und LibGfx, Swift-Frontend-Abstürze und Konflikte bei Typ-Namensräumen
- Diese kumulierten technischen Einschränkungen führten dazu, dass die Swift-Integration eingestellt wurde; daraus folgte die Entscheidung, die Entwicklung mit Fokus auf C++ fortzuführen
Probleme im Zusammenhang mit Swift
- Es gab zahlreiche Fehler auf Sprach- und ABI-Ebene, die behoben werden mussten, damit der Swift-6.0-Support den experimentellen Status verlassen konnte
- Beim Open-Source-Build von Swift traten aufgrund nicht übereinstimmender LLVM-Versionen Assertion-Fehler auf
- Bei der Rückgabe von
Optional<CxxValueType>kam es zu ABI-Inkonsistenzen zwischen Compiler und Bridging-Header - Unter Ubuntu 22.04 entstanden beim Einbinden des Headers
<execution>zirkuläre Modulabhängigkeiten in libstdc++ - Enthalten waren auch Kompatibilitätsprobleme mit C++23, etwa die fehlende Möglichkeit,
swift::Optional<swift::String>zurückzugeben, oder das Scheitern beim Laden des Headers<chrono>
- Einige Probleme wurden in Releases nach Swift 6.0.0 behoben, andere jedoch nur im main-Branch, sodass sie nicht in stabile Versionen eingeflossen sind
- Für mehrere Punkte wurden „Workarounds (Umgehungen beim Build)“ vorgeschlagen, diese stellen jedoch keine vollständige Lösung dar
Probleme im Zusammenhang mit CMake
- In der Kombination aus Swift und Ninja-Build wurde
CMAKE_OSX_DEPLOYMENT_TARGETnicht angewendet, was zu zahlreichen Warnungen führteCMAKE_Swift_COMPILER_TARGETmusste manuell gesetzt werden
- Bei aktivierter Richtlinie CMP0157 wurde die Einstellung des install_name-Verzeichnisses ignoriert, sodass eine manuelle Korrektur nötig war
- Ein entsprechender Fix soll auf CMake 3.29 und 3.30 zurückportiert werden
- Es gab ein Problem, bei dem Linker-Optionen, die der Swift-Compiler nicht versteht, aus externen Abhängigkeiten weitergereicht wurden
Interne Probleme im Ladybird-Projekt
- Bei der clang-modulemap-Konfiguration der Module AK und LibGfx kam es zu Konflikten mit System-Headern
- Beim Einbinden von
<math.h>schlug der Build wegen eines Fehlers bei der Modulerkennung fehl
- Beim Einbinden von
- Das Swift-Frontend stürzte in Debug-Builds während AK-Containertests ab
- Umgehbar war dies nur durch Builds im Release-Modus
- Ein Konflikt im Namensraum des Typs
Stringführte zu einem unerwarteten Abbruch des Swift-Frontends- Eine explizite Angabe als
AK.StringoderSwift.Stringwar erforderlich
- Eine explizite Angabe als
- Bei Verwendung des Swift-Testing-Moduls traten Frontend-Abstürze des Compilers auf; außerdem wurde
AK::StringViewnicht alsCxxSequenceTypeerkannt
Zusätzliche Verbesserungsbereiche
- Wenn C++-Funktionen in Swift
Optional<CxxType>zurückgeben, kam es zu Anwendungsabstürzen- Als temporärer Workaround wurde die Rückgabe eines Arrays der Größe 0 oder 1 verwendet
- SourceKit-LSP und vscode-swift verlangen
compile_commands.jsonauf Root-Ebene- Dies lässt sich durch das Erstellen eines symbolischen Links lösen
- Unter Linux bestand die Unannehmlichkeit, dass der Pfad
<swift/bridging>manuell hinzugefügt werden musste
Offene Fragen
- Es ist unklar, wie sich in Swift C++-View-Typen oder Byte-Slices ohne Kopie übergeben lassen
- Swift erkennt eigene Typen wie
AK::OptionaloderAK::HashMapnicht als gleichwertig zustd::-Typen - Auch die Integration des Swift-Garbage-Collectors in Ladybirds Speicherverwaltung war noch ungeklärt
Dieses Issue war zwar ein Dokument zur systematischen Erfassung technischer Hürden für die Swift-6.0-Integration, wurde jedoch abgeschlossen, nachdem das Ladybird-Team die Einführung von Swift eingestellt hatte; damit wurde auch das Issue „Swift 6.0 Blockers“ beendet.
1 Kommentare
Hacker-News-Kommentare
Der Commit zum Entfernen von Swift enthält noch etwas zusätzliche Erklärung.
Er enthält die Nachricht: „Da es lange keine Fortschritte gab, wurde die Einführung von Swift aufgegeben und aus der Codebasis entfernt.“
Den zugehörigen Commit gibt es hier.
Ich habe Swift 2021 zum ersten Mal ausprobiert und war überrascht, nachdem ich über 10 Jahre mit C#/.NET gearbeitet hatte.
Ich hielt schon C# für komplex, aber Swift war eine noch deutlich komplexere Sprache.
Vor allem beim Erstellen von Backend-APIs oder einer Datenzugriffsschicht gab es fast kein Referenzmaterial.
Das Wissen zu Swift ist größtenteils für Apple-Plattformen aufgebaut, sodass man sich außerhalb davon fast wie ein Pionier fühlt.
Wie Larry Wall sagte, sollte die Komplexität des Werkzeugs zur Komplexität des Problems passen (mit Verweis auf Raku).
Aber Regeln wie „struct wird per Wert übergeben, class per Referenz“ kollidierten mit dem Prinzip einer „Single Source of Truth“, wodurch sich die Entwicklung langweilig und langsam anfühlte.
Wegen widersprüchlicher Best Practices in Swift gab es keine Fortschritte, und am Ende wurde mir klar, dass man vielen Ratschlägen nicht trauen konnte.
Es gibt zu viel syntactic sugar, und für dieselbe Sache gibt es Dutzende Wege, sodass ich ständig in der Sprachreferenz nachsehen musste.
Unabhängig von der Sprache hoffe ich, dass sich Ladybird später auf eine nutzerfreundliche JavaScript-Implementierung konzentriert.
Es ist problematisch, dass JS für Nutzer-Tracking, das Blockieren von Einfügen oder das exzessive Sammeln von Geräteinformationen missbraucht wird.
Wenn wie bei Tor standardisierte Spoofing-Werte für alle Nutzer gemeldet würden, könnte das dem Schutz der Privatsphäre helfen.
Als umschaltbare Option wäre das okay, aber als Standard dürfte die Akzeptanz schwierig werden.
Dass Swift entfernt wurde, ist interessant. Die Gründe wurden nicht klar erklärt, daher bin ich neugierig.
Wenn es nur unter Linux läuft, würde ich es später trotzdem einmal testen.
Es gab Probleme damit, dass Swift nicht mehrere Bibliotheken mit unterschiedlichen C++-Versionen gleichzeitig importieren konnte oder dass Operator-Versionen kollidierten.
Swift ist zwar eine gute Sprache, aber für die nachträgliche Einführung in ein bereits großes Projekt war es wohl zu komplex.
Ich frage mich, warum Ladybird Swift ausprobiert hat. Ich hätte gedacht, dass Rust eine bessere C++-Interoperabilität hat.
Auch Swifts GC scheint für Browser-Performance nachteilig zu sein.
Link1, Link2
Es gibt Workarounds, aber sie kosten Produktivität.
Für Ladybird scheint es allerdings nicht gereicht zu haben.
Früher entstand in SerenityOS sogar die Sprache Jakt, aber am Ende scheint man doch wieder bei C++ gelandet zu sein.
Die frühere Diskussion dazu findet sich in diesem Beitrag.
Es überrascht mich nicht, dass Swift entfernt wurde, weil es eine zu stark von Apple abhängige Sprache ist.
Es reicht völlig, nur die sicheren Teile von C++ sauber zu verwenden, und tatsächlich sind die meisten Browser in C++ geschrieben.
Chromium und Firefox ersetzen schrittweise Teile durch sicherere Sprachen, und einen neuen Browser erneut in C++ zu schreiben hieße, die Fehler der Vergangenheit zu wiederholen.
Die Verwendung von C++ ist ein Erbe aus der KHTML-Zeit von 1998.
Sind damit auch neuere STL-Features wie string_view gemeint? Von vollständiger Speichersicherheit ist das immer noch weit entfernt.
Abgesehen von einigen Benchmarks ist es in realen Programmen fast immer langsamer.
Schade, dass Swift entfernt wurde. Ich frage mich, ob damit die eigene Sprache Jakt wieder als Kandidat auf den Tisch kommt.
Ich halte es für unwahrscheinlich, dass noch einmal eine neue Sprache eingeführt wird.
Für ein Projekt, das durch externe Förderung betrieben wird, dürfte so etwas langfristig schwer tragfähig sein.
Ich halte Swift letztlich nur für eine Spielzeugsprache von Apple.
Apple wird nicht zulassen, dass sie darüber hinauswächst.
Die Mac-UI von Ladybird ist eine dünne Schicht auf AppKit.
Sie ist nicht in Swift, sondern in Objective-C++ geschrieben.
Siehe den Quellcode.
Er entstand lange vor der Einführung von Swift, noch in der SerenityOS-Zeit, und ich habe Objective-C++ nur verwendet, weil es mir vertraut war.
Als damals von einer Umstellung auf Swift die Rede war, habe ich das kritisiert.
Ich fand, Swift sei schlecht entworfen, langsam beim Kompilieren und habe wenig Aussicht, sich als Systemsprache zu etablieren.
Es gab auch keine Experten, daher halte ich die jetzige Entscheidung für richtig.
Funktionen wie Concurrency oder Swift Testing wurden ebenfalls nach Apples Bedarf vorangetrieben.
Cross-Platform-Arbeit wird größtenteils separat von kleinen Teams betrieben.
Auch abgesehen von Chris Lattner waren die Swift-Leads in der C++-Community anerkannte Persönlichkeiten.
Es wäre schön, wenn das Rust-Lager neben C auch die Swift-ABI für FFI unterstützen würde.