1 puntos por GN⁺ 5 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Zig, en línea con el flujo que separa build.zig y el sistema de build en procesos separados, trasladó la lógica de gestión de paquetes fuera del ejecutable del compilador, al proceso maker
  • Al mover zig build, zig fetch, zig init y zig libc al lado del maker, el código de manejo de HTTP, TLS, Git, compresión y build.zig.zon se distribuye en forma de código fuente
  • Con esta estructura, las funciones de gestión de paquetes pueden corregirse sin recompilar el compilador, y como el maker se compila en ReleaseSafe, también se activan las verificaciones de seguridad para las tareas de networking
  • El objetivo original es exponer el build server protocol para resolver el problema con el cambio de --build-runner que estaba bloqueando a ZLS; en el nuevo árbol de procesos, el maker permanece como padre del configurer y puede manejar de forma más estable la reejecución de la configuración
  • El impacto para los usuarios no es grande, pero el ejecutable de Zig se reduce un 4%, de 14.1 MiB a 13.5 MiB, y --maker-opt y --zig-lib-dir se reemplazan por las variables de entorno ZIG_DEBUG_MAKER y ZIG_LIB_DIR, respectivamente

Traslado de la lógica de gestión de paquetes

  • Después de separar el script de usuario build.zig y el propio sistema de build en procesos distintos, Zig cambió a una estructura en la que también ubica la lógica de gestión de paquetes del lado del sistema de build
  • Los subcomandos trasladados al proceso maker son los siguientes
    • zig build
    • zig fetch
    • zig init
    • zig libc

Código que salió del ejecutable del compilador

  • Grandes áreas de código que antes estaban dentro del ejecutable del compilador ahora se distribuyen en forma de código fuente
    • Lógica para obtener paquetes
    • Cliente HTTP y networking
    • TLS y criptografía relacionada
    • Protocolo Git
    • xz, gzip, zstd, flate, zip
    • Parseo, validación y otros procesamientos del archivo build.zig.zon
  • Estas funciones pueden parchearse sin volver a compilar el compilador, lo que facilita a usuarios y contribuidores experimentar
  • El ejecutable maker se compila en modo ReleaseSafe, por lo que las verificaciones de seguridad quedan activadas en las tareas de networking de la gestión de paquetes
  • El código criptográfico usado para networking y hashing de archivos puede aprovechar instrucciones especiales de CPU disponibles en el host

Estructura de procesos y build server

  • La motivación original era exponer el build server protocol para resolver el problema que estaba bloqueando a ZLS
  • En la estructura anterior, zig build se encargaba tanto del compilador como del gestor de paquetes, y debajo de este el builder contenía la lógica del build.zig del usuario y la implementación del sistema de build
  • Después de la separación maker/configurer, la estructura era la siguiente
    • zig build: compilador + gestor de paquetes
    • configurer: lógica del build.zig del usuario
    • maker: sistema de build
  • En esta estructura, zig build --watch, que se ejecuta por mucho tiempo, debía volver a ejecutar el configurer cuando detectaba cambios en build.zig o en archivos relacionados; para eso, el maker tenía que terminar y darle a zig build la oportunidad de repetir la lógica de gestión de paquetes
  • En la nueva estructura, zig build solo se encarga del compilador, mientras que debajo de él el maker se encarga del sistema de build y del gestor de paquetes, y el configurer pasa a ser un proceso hijo del maker
  • Incluso cuando sea necesario volver a ejecutar la configuración, el maker puede seguir vivo como proceso padre
  • En el build server previsto, en lugar de que el cliente vuelva a conectarse después de que el servidor termine, será posible una estructura que notifique al cliente los cambios de configuración

Cambios observables

  • La mayoría no son cambios incompatibles, pero hay diferencias visibles para los usuarios
    • Tamaño del binario ejecutable de Zig: en ReleaseSmall sin LLVM, baja de 14.1 MiB a 13.5 MiB, una reducción del 4%
    • La bandera --maker-opt se reemplaza por la variable de entorno ZIG_DEBUG_MAKER
    • La bandera --zig-lib-dir se reemplaza por la variable de entorno ZIG_LIB_DIR

Problemas bloqueantes pendientes antes de Zig 0.17.0

1 comentarios

 
GN⁺ 5 시간 전
Opiniones en Hacker News
  • Los desarrolladores de Zig, Go y Python a veces anuncian que sacaron el refrigerante del tanque de combustible, y sus partidarios celebran diciendo que será bueno para el lenguaje y que el rendimiento mejorará muchísimo.
    Pero me da más curiosidad por qué, para empezar, habían puesto refrigerante en el tanque de combustible.

    • En las etapas iniciales de proyectos así, suele priorizarse la comodidad de los desarrolladores individuales antes que pensar a fondo en las consecuencias del diseño.
      Meter la gestión de paquetes dentro del compilador era cómodo, pero cuando el lenguaje y las herramientas empiezan a usarse ampliamente, una funcionalidad que favorecía a una persona se convierte en deuda que frena la adopción.
      En muchos proyectos, los desarrolladores eligen el camino cómodo para evitar “el trabajo difícil necesario para hacerlo bien”, y como otros tampoco quieren hacer ese trabajo difícil, eso termina volviéndose la práctica habitual.
    • También hay una lógica defendible en esto.
      Si vas a implementar un gestor de paquetes dentro del sistema de build y también quieres mantenerlo en el compilador, primero tienes que decidir qué abstracción poner entre el compilador y el sistema de build.
      Eso también afecta al sistema de import y a partes fundamentales del lenguaje, y esas partes hay que diseñarlas bien; además, son difíciles de cambiar después.
      Al principio puede tener menos impacto para los usuarios acoplar fuertemente la gestión de paquetes y el compilador, diseñar hacia atrás desde la experiencia de programación deseada y luego cambiar la implementación más adelante.
      En particular, creo que el sistema de import de Python se volvió muy complejo y lleno de defectos por tener que adaptarse a varias formas de gestión de paquetes.
      En cambio, Go se diseñó desde el inicio pensando en la gestión de paquetes, así que la sintaxis relacionada con imports es relativamente pequeña y limpia. Claro que no estoy de acuerdo con todas sus decisiones de diseño.
    • Suena a que nunca has creado algo.
      Incluso en un producto pequeño es difícil predecir cómo interactuará cada componente, así que hay que corregirlo constantemente.
      Ahora imagina crear un lenguaje autoalojado que reemplace a C.
    • Siento exactamente lo mismo sobre el rendimiento. No tiene que ver con un lenguaje de programación específico ni con mis optimizaciones.
      Mientras mayor es la mejora de velocidad, más se celebra, pero la mayoría de las optimizaciones no son técnicas ingeniosas, sino usar un profiler para encontrar cosas tipo “eh, el refrigerante no debería estar en el tanque de combustible”.
      La mayoría de los cuellos de botella de rendimiento no son límites esenciales del hardware ni del problema en sí.
      Hay una cantidad mínima de trabajo necesaria para obtener el resultado, pero casi siempre las aplicaciones son lentas por toda la chatarra que se les agregó encima.
    • No conozco lo suficiente Zig o Python como para juzgar, pero con Go no tengo esa sensación en absoluto. No sé cuándo habría pasado algo así.
  • El desarrollo de Zig realmente se siente como un ambiente sano.

    • Ver Zig hoy demuestra que el craft del desarrollo de software no está muerto ni fue reemplazado por los LLM.
      Uso LLM todos los días y reconozco que son sorprendentemente buenos para varios tipos de problemas, pero no quiero un lenguaje de programación creado por un LLM.
      Cada línea de código, decisión y compromiso en un lenguaje de programación importa.
      Un lenguaje diseñado y programado solo por vibes sería un desastre.
      Ningún modelo me ha mostrado código que me convenza de lo contrario. Incluso Fable, aunque claramente mejoró frente al mejor modelo anterior, sigue igual en ese sentido.
      Los modelos no quieren nada, no tienen opiniones significativas y no saben qué se siente cómodo o incómodo en un lenguaje. Lo mismo aplica a interfaces GUI o CLI suficientemente complejas.
      Un lenguaje como Zig no podría salir de un LLM a menos que simplemente copiara Zig, e incluso si lo copiara sería una copia peor.
      Con copiar mediante LLM no me refiero a hacer literalmente cp del árbol de fuentes, sino a que un LLM escriba la especificación y otro LLM implemente el lenguaje según esa especificación.
    • También es bastante divertido construir cosas con Zig.
      Hice un bootloader y trabajé con UEFI, y personalmente me resultó mucho más fácil que hacerlo en C.
      Aunque también es cierto que puede haber sesgo porque aprender algo nuevo y brillante es divertido.
  • Me pregunto si este es el cambio que hizo que Zig quitara @cImport y lo moviera al sistema de build.
    Es puramente un tema de experiencia de usuario, y entiendo que separar el sistema de build del compilador es importante para los maintainers, pero aun así me da un poco de pena que la estabilidad del desarrollo vaya antes que la experiencia de usuario.
    Es la decisión correcta, pero triste; creo que @cImport era una killer feature potente del lenguaje.

    • No necesariamente.
      Este cambio trata del código que descarga y descomprime paquetes de terceros.
      El cambio de @cImport fue parte del trabajo para que la dependencia de Zig en LLVM/libclang algún día sea opcional y, más adelante, pueda moverse a un paquete de terceros, pero no parece estar directamente relacionado.
  • Leí en algún lado que el objetivo a largo plazo es mover el sistema de build dentro de una VM de WebAssembly.
    Si es así, sería algo impresionante.

    • Me pregunto qué ventajas tendría eso en un build.
  • Es un buen cambio para Zig.
    Tengo bastantes ganas de pasarme de Go a Zig, pero por ahora también disfruto mirar desde afuera.

    • Según el caso de uso, puedes usar ambos, y quizá deberías.
  • Cada vez que un lenguaje crea su propio sistema de paquetes, solo siento que perdimos una gran oportunidad.
    La única excepción es C/C++, donde, para bien o para mal, no hay nada suficientemente establecido.
    Esta elección puede crear procedimientos muy complejos más adelante, cuando necesitas mezclar varios lenguajes.
    Los sistemas de empaquetado facilitan las cosas, pero en el momento en que necesitas usar otro lenguaje, complican todo lo que sigue.

    • Me da curiosidad qué crees que se perdió.
      ¿Quieres un único sistema de build para todos los lenguajes? Existen sistemas como Bazel y se usan con frecuencia en proyectos multilenguaje, pero en la práctica parece haber quedado demostrado que un sistema de build con conocimiento específico del lenguaje es mucho más fácil de manejar.
    • Creo que es algo bueno que C++ no tenga un sistema de empaquetado estandarizado.
      Porque te obliga a pensarlo bien antes de agregar dependencias.
      Esas dependencias suelen tener costos ocultos, como vulnerabilidades de seguridad.
      Como muchos sistemas importantes están escritos en C++, depender de decenas de paquetes de terceros fácilmente accesibles sin auditar bien cada paquete es demasiado riesgoso.
    • C debería haber corregido varios problemas y agregado un gestor de paquetes, o haber reconocido oficialmente alguno.
      Zig está llenando ese vacío.
    • El mundo todavía no ha logrado estandarizarse en un buen sistema de build multiplataforma y multilenguaje.
      En la práctica, los únicos sistemas de build de ese tipo son Buck y Bazel, pero ambos cargan con demasiado equipaje de las enormes organizaciones que tienen detrás.
      Es una lástima.
    • Conan y vcpkg están suficientemente establecidos.
  • La separación de responsabilidades se hizo de una manera muy convincente.