1 Punkte von GN⁺ 5 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • Passend zu Zigs Ablauf, bei dem build.zig und das Build-System in separate Prozesse aufgeteilt wurden, wurde die Paketverwaltungslogik aus der ausführbaren Compiler-Datei in den maker-Prozess verschoben
  • Mit der Verlagerung von zig build, zig fetch, zig init und zig libc auf die maker-Seite werden HTTP, TLS, Git, Kompression und der Code zur Verarbeitung von build.zig.zon als Quellcode ausgeliefert
  • In dieser Struktur lassen sich Paketverwaltungsfunktionen ohne Neu-Build des Compilers korrigieren, und da der maker mit ReleaseSafe kompiliert wird, sind auch Sicherheitsprüfungen für Netzwerkoperationen aktiviert
  • Ursprüngliches Ziel war es, durch Offenlegung des build server protocol ein Problem mit --build-runner-Änderungen zu lösen, das ZLS blockierte; im neuen Prozessbaum bleibt der maker Elternprozess des configurer und kann erneutes Ausführen der Konfiguration stabiler handhaben
  • Für Nutzer ändert sich wenig, aber die Zig-Executable schrumpft um 4 % von 14,1 MiB auf 13,5 MiB, und --maker-opt sowie --zig-lib-dir werden durch die Umgebungsvariablen ZIG_DEBUG_MAKER bzw. ZIG_LIB_DIR ersetzt

Verlagerung der Paketverwaltungslogik

  • Nachdem Zigs Nutzer-Skript build.zig und das Build-System selbst in separate Prozesse aufgeteilt wurden, wurde die Struktur so geändert, dass auch die Paketverwaltungslogik auf der Seite des Build-Systems liegt
  • Die in den maker-Prozess verschobenen Unterbefehle sind:
    • zig build
    • zig fetch
    • zig init
    • zig libc

Code, der aus der Compiler-Executable entfernt wurde

  • Große Codebereiche, die zuvor in der Compiler-Executable enthalten waren, werden nun als Quellcode ausgeliefert
    • Logik zum Abrufen von Paketen
    • HTTP-Client und Networking
    • TLS und zugehörige Kryptografie
    • Git-Protokoll
    • xz, gzip, zstd, flate, zip
    • Parsing, Validierung und sonstige Verarbeitung von build.zig.zon-Dateien
  • Diese Funktionen können ohne Neu-Build des Compilers gepatcht werden, wodurch Nutzer und Beitragende leichter experimentieren können
  • Die maker-Executable wird im Modus ReleaseSafe kompiliert, daher sind bei Netzwerkoperationen der Paketverwaltung Sicherheitsprüfungen aktiviert
  • Der für Networking und Datei-Hashing verwendete kryptografische Code kann auf dem Host verfügbare spezielle CPU-Instruktionen nutzen

Prozessstruktur und build server

  • Die ursprüngliche Motivation war, das build server protocol offenzulegen und damit ein Problem zu beseitigen, das ZLS blockierte
  • In der früheren Struktur war zig build zugleich für Compiler und Paketmanager zuständig, darunter enthielt der builder die Logik des Nutzer-build.zig und die Implementierung des Build-Systems
  • Nach der Trennung von maker/configurer sah die Struktur wie folgt aus:
    • zig build: Compiler + Paketmanager
    • configurer: Nutzer-build.zig-Logik
    • maker: Build-System
  • In dieser Struktur musste ein lange laufendes zig build --watch den configurer erneut ausführen, wenn Änderungen an build.zig oder zugehörigen Dateien erkannt wurden; dafür musste der maker beendet werden, damit zig build die Paketverwaltungslogik erneut ausführen konnte
  • In der neuen Struktur übernimmt zig build nur den Compiler, während darunter der maker Build-System und Paketmanager verwaltet; der configurer wird ein Kindprozess des maker
  • Auch wenn die Konfiguration erneut ausgeführt werden muss, kann der maker als Elternprozess weiterlaufen
  • Beim geplanten build server wird dadurch eine Struktur möglich, bei der der Client über Konfigurationsänderungen informiert wird, statt dass er sich nach dem Beenden des Servers erneut verbindet

Sichtbare Änderungen

  • Die meisten Änderungen sind nicht inkompatibel, es gibt aber für Nutzer sichtbare Unterschiede
    • Binärgröße der Zig-Executable: auf Basis von ReleaseSmall ohne LLVM von 14,1 MiB auf 13,5 MiB reduziert, also 4 % kleiner
    • Das Flag --maker-opt wird durch die Umgebungsvariable ZIG_DEBUG_MAKER ersetzt
    • Das Flag --zig-lib-dir wird durch die Umgebungsvariable ZIG_LIB_DIR ersetzt

Verbleibende blockierende Issues vor Zig 0.17.0

1 Kommentare

 
GN⁺ 5 시간 전
Hacker-News-Kommentare
  • Zig-, Go- und Python-Entwickler verkünden gelegentlich, sie hätten Kühlmittel aus dem Kraftstofftank entfernt, und ihre Anhänger jubeln, das sei gut für die Sprache und werde die Performance deutlich verbessern.
    Dabei frage ich mich eher, warum das Kühlmittel überhaupt im Kraftstofftank war.

    • In frühen Phasen solcher Projekte steht oft eher die Bequemlichkeit einzelner Entwickler im Vordergrund als ein gründliches Durchdenken der Designfolgen.
      Paketverwaltung in den Compiler zu packen war bequem, aber sobald Sprache und Werkzeuge breiter genutzt werden, wird eine Funktion, die für Einzelne vorteilhaft war, zu technischer Schuld, die Adoption verhindert.
      In vielen Projekten wählen Entwickler den bequemen Weg, um „die schwierige Arbeit, die für eine saubere Lösung nötig wäre“ zu vermeiden; und weil andere diese schwierige Arbeit ebenfalls nicht machen wollen, wird daraus eine Konvention.
    • Dafür gibt es aber auch eine verteidigbare Logik.
      Wenn man einen Paketmanager im Build-System implementiert und ihn gleichzeitig im Compiler belassen will, muss man zuerst festlegen, welche Abstraktion zwischen Compiler und Build-System liegen soll.
      Das wirkt sich auch auf das Import-System und grundlegende Teile der Sprache aus; solche Dinge müssen sauber entworfen werden und lassen sich später nur schwer ändern.
      Anfangs Paketverwaltung und Compiler eng zu koppeln und ausgehend von der gewünschten Programmiererfahrung rückwärts zu entwerfen, um später die Implementierung zu ändern, kann für Nutzer weniger Auswirkungen haben.
      Besonders Pythons Import-System halte ich für sehr komplex und fehlerbehaftet, weil es viele Arten der Paketverwaltung aufnehmen musste.
      Go dagegen wurde von Anfang an mit Paketverwaltung im Hinterkopf entworfen, weshalb die importbezogene Syntax vergleichsweise klein und sauber ist. Natürlich stimme ich nicht jeder Designentscheidung zu.
    • Das klingt so, als hättest du noch nie etwas gebaut.
      Selbst bei kleinen Produkten ist schwer vorherzusagen, wie die einzelnen Komponenten interagieren werden, und man muss ständig nachbessern.
      Jetzt stell dir vor, du baust eine selbsthostende C-Ersatzsprache.
    • Bei Performance habe ich exakt dasselbe Gefühl. Das hat nichts mit einer bestimmten Programmiersprache oder meinen Optimierungen zu tun.
      Je größer die Beschleunigung, desto mehr Jubel, aber die meisten Optimierungen sind keine cleveren Tricks, sondern bestehen darin, mit dem Profiler festzustellen: „Oh, Kühlmittel gehört nicht in den Kraftstofftank.“
      Die meisten Performance-Engpässe sind keine inhärenten Grenzen der Hardware oder des Problems selbst.
      Es gibt ein Mindestmaß an Arbeit, das nötig ist, um ein Ergebnis zu bekommen, aber der Grund, warum Anwendungen langsam sind, liegt fast immer in dem Gerümpel, das man obendrauf gepackt hat.
    • Zig oder Python kenne ich nicht gut genug, um das zu beurteilen, aber bei Go habe ich dieses Gefühl überhaupt nicht. Ich weiß nicht, wann das passiert sein soll.
  • Die Entwicklung von Zig wirkt wirklich wie eine gesunde Atmosphäre.

    • Wenn ich mir Zig heutzutage ansehe, beweist es, dass das Craft der Softwareentwicklung nicht tot ist und auch nicht durch LLMs ersetzt wurde.
      Ich nutze LLMs täglich und räume ein, dass sie bei vielen Problemtypen erstaunlich gut sind, aber ich will keine Programmiersprache, die von einem LLM geschaffen wurde.
      Jede Codezeile, jede Entscheidung und jeder Kompromiss in einer Programmiersprache ist wichtig.
      Eine Sprache, die nur nach Gefühl designt und codiert wurde, wäre eine Katastrophe.
      Kein Modell hat mir je Code gezeigt, der mich vom Gegenteil überzeugt hätte. Selbst Fable, das klar besser ist als die bisherigen besten Modelle, ändert daran nichts.
      Modelle haben keine eigenen Wünsche, keine sinnvollen Ansichten und wissen nicht, was sich in einer Sprache angenehm oder unangenehm anfühlt. Dasselbe gilt für ausreichend komplexe GUI- oder CLI-Interfaces.
      Eine Sprache wie Zig kann aus einem LLM nicht hervorgehen, solange es Zig nicht einfach kopiert; und selbst dann wäre es eine schlechtere Kopie.
      Mit „per LLM kopieren“ meine ich hier nicht, den Source-Tree buchstäblich mit cp zu kopieren, sondern dass ein LLM eine Spezifikation schreibt und ein anderes LLM die Sprache nach dieser Spezifikation implementiert.
    • Mit Zig zu bauen macht auch ziemlich viel Spaß.
      Ich habe einen Bootloader gebaut und mit UEFI gearbeitet, und persönlich fand ich es deutlich einfacher als mit C.
      Allerdings ist sicher auch ein Bias dabei, weil es Spaß macht, etwas Neues und Glänzendes zu lernen.
  • Ich frage mich, ob diese Änderung diejenige ist, die dazu geführt hat, dass @cImport aus Zig entfernt und ins Build-System verlagert wurde.
    Es ist rein eine Frage der User Experience, und ich verstehe, dass die Trennung von Build-System und Compiler für die Maintainer wichtig ist, aber trotzdem ist es ein wenig schade, dass Entwicklungsstabilität vor User Experience kommt.
    Es ist die richtige Entscheidung, aber traurig; @cImport war meiner Meinung nach ein starkes Killer-Feature der Sprache.

    • Nicht unbedingt.
      Diese Änderung betrifft den Code zum Herunterladen und Entpacken von Third-Party-Paketen.
      Die Änderung an @cImport war Teil der Arbeit daran, Zigs LLVM/libclang-Abhängigkeit irgendwann optional zu machen und später in ein Third-Party-Paket auslagern zu können, scheint aber nicht direkt damit zusammenzuhängen.
  • Ich habe irgendwo gelesen, dass das langfristige Ziel darin besteht, das Build-System in eine WebAssembly-VM zu verlagern.
    Wenn das stimmt, wäre das eine große Sache.

    • Ich frage mich, welchen Vorteil das für Builds hätte.
  • Eine gute Änderung für Zig.
    Ich bin ziemlich versucht, von Go zu Zig zu wechseln, aber vorerst genieße ich es auch, von der Seitenlinie zuzusehen.

    • Je nach Use Case kann man beide verwenden, und vielleicht sollte man das sogar.
  • Jedes Mal, wenn eine Sprache ihr eigenes Paketsystem baut, habe ich nur das Gefühl, dass wir eine große Chance verpasst haben.
    Die einzige Ausnahme ist C/C++, wo sich, im Guten wie im Schlechten, nichts ausreichend etabliert hat.
    Solche Entscheidungen können später sehr komplexe Abläufe erzeugen, wenn man mehrere Sprachen mischen muss.
    Packaging-Systeme machen Dinge einfacher, aber sobald man eine andere Sprache verwenden muss, machen sie den weiteren Prozess komplizierter.

    • Mich würde interessieren, was deiner Ansicht nach verpasst wurde.
      Willst du ein einziges Build-System für alle Sprachen? Systeme wie Bazel gibt es, und sie werden oft für mehrsprachige Projekte genutzt, aber in der Praxis scheint sich gezeigt zu haben, dass ein Build-System mit sprachspezifischem Wissen deutlich leichter zu handhaben ist.
    • Dass C++ kein standardisiertes Packaging-System hat, halte ich sogar für gut.
      Es zwingt einen nämlich, sorgfältig nachzudenken, bevor man eine Abhängigkeit hinzufügt.
      Solche Abhängigkeiten haben oft versteckte Kosten, etwa Sicherheitslücken.
      Da ein erheblicher Teil wichtiger Systeme in C++ geschrieben ist, wäre es viel zu riskant, sich auf Dutzende leicht zugängliche Third-Party-Pakete zu verlassen, ohne jedes davon ordentlich zu auditieren.
    • C hätte mehrere Probleme beheben und einen Paketmanager hinzufügen oder offiziell anerkennen sollen.
      Zig füllt diese Lücke.
    • Die Welt hat sich noch nicht auf ein gutes plattformübergreifendes, mehrsprachiges Build-System standardisiert.
      Praktisch gibt es dafür nur Buck und Bazel, aber beide bringen zu viel Ballast der großen Organisationen mit, aus denen sie stammen.
      Das ist schade.
    • Conan und vcpkg sind ausreichend etabliert.
  • Die Trennung der Zuständigkeiten wurde sehr nachvollziehbar umgesetzt.