Zig: mueve todas las funciones de gestión de paquetes del compilador al sistema de build
(ziglang.org)- Zig, en línea con el flujo que separa
build.zigy 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 inityzig libcal lado del maker, el código de manejo de HTTP, TLS, Git, compresión ybuild.zig.zonse 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-runnerque 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-opty--zig-lib-dirse reemplazan por las variables de entornoZIG_DEBUG_MAKERyZIG_LIB_DIR, respectivamente
Traslado de la lógica de gestión de paquetes
- Después de separar el script de usuario
build.zigy 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 buildzig fetchzig initzig 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 buildse encargaba tanto del compilador como del gestor de paquetes, y debajo de este el builder contenía la lógica delbuild.zigdel 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 paquetesconfigurer: lógica delbuild.zigdel usuariomaker: 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 enbuild.zigo en archivos relacionados; para eso, el maker tenía que terminar y darle azig buildla oportunidad de repetir la lógica de gestión de paquetes - En la nueva estructura,
zig buildsolo 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
ReleaseSmallsin LLVM, baja de 14.1 MiB a 13.5 MiB, una reducción del 4% - La bandera
--maker-optse reemplaza por la variable de entornoZIG_DEBUG_MAKER - La bandera
--zig-lib-dirse reemplaza por la variable de entornoZIG_LIB_DIR
- Tamaño del binario ejecutable de Zig: en
Problemas bloqueantes pendientes antes de Zig 0.17.0
- Tras este conjunto de cambios, los principales problemas bloqueantes restantes son el trabajo clave antes de la etiqueta Zig 0.17.0
- Como en julio habrá dos conferencias y preparación de presentaciones, se espera que el cierre de estos trabajos sea, de manera realista, a principios de agosto
- Techatrix del equipo de ZLS se puso en contacto y colaboró en el trabajo del build server protocol, y está buscando patrocinio
1 comentarios
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.
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.
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.
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.
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.
El desarrollo de Zig realmente se siente como un ambiente sano.
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
cpdel árbol de fuentes, sino a que un LLM escriba la especificación y otro LLM implemente el lenguaje según esa especificación.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
@cImporty 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
@cImportera una killer feature potente del lenguaje.Este cambio trata del código que descarga y descomprime paquetes de terceros.
El cambio de
@cImportfue 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.
Es un buen cambio para Zig.
Tengo bastantes ganas de pasarme de Go a Zig, pero por ahora también disfruto mirar desde afuera.
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.
¿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.
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.
Zig está llenando ese vacío.
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.
La separación de responsabilidades se hizo de una manera muy convincente.