1 puntos por GN⁺ 5 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Nix Flakes agrupa las dependencias del proyecto, el bloqueo, el esquema de salidas y el entorno de desarrollo alrededor de flake.nix y flake.lock, mientras que Guix ofrece el mismo tipo de funciones mediante una combinación de herramientas ortogonales como channels, manifests, guix describe, guix shell y operating-system
  • Flakes fija las dependencias con inputs por proyecto y un flake.lock automático, mientras que Guix construye entornos reproducibles con guix describe por usuario, channels.scm con commits anotados en el proyecto y guix time-machine
  • La pureza se impone en Flakes mediante restricted evaluation, mientras que en Guix se logra por diseño a través de la estructura de módulos de Scheme, entradas explícitas y contenedores de compilación aislados
  • En cuanto a la estructura de salidas, Flakes ofrece attrsets estándar como packages, devShells y nixosConfigurations, mientras que Guix usa registros y archivos transparentes de Scheme como <package>, manifest, operating-system y service, que cada comando consume directamente
  • El criterio de elección es que si prefieres un único punto de entrada y un esquema estándar, Flakes encaja mejor; si prefieres combinar herramientas pequeñas e independientes, Guix se ajusta mejor

Comparación clave

  • No existe una sola función de Guix equivalente a un Nix flake; mientras Nix Flakes resuelve varios problemas con una gran función unificada, Guix responde con una combinación de herramientas más pequeñas y ortogonales
  • Guix reutilizó el daemon de Nix y comparte los componentes en C++ encargados del aislamiento de compilación y la gestión del store
  • Guix reimplementa desde cero en Guile Scheme la mayor parte de lo que está por encima del daemon de Nix, como el lenguaje, las definiciones de paquetes y el sistema de servicios
  • Guix y Nix comparten el formato de derivación ATerm y el linaje del daemon, pero la estructura por encima del daemon está organizada a la manera propia de Guix
  • Guix tiene las capacidades que ofrecen Flakes, pero las presenta de una forma distinta

Estructura básica de un Nix Flake

  • Un Nix flake es un árbol de código fuente con un archivo flake.nix en la raíz, normalmente en forma de repositorio Git
  • La presencia de flake.nix convierte al árbol de código fuente en un flake, y el archivo tiene una estructura con elementos como description, inputs y outputs
  • description es una cadena legible por humanos que indica lo que ofrece el flake
  • inputs declara dependencias como otros flakes, repositorios Git o tarballs; Nix las obtiene, las evalúa y luego las pasa a la función outputs
  • outputs es una función que recibe los inputs resueltos y un input especial self, y devuelve un attrset estructurado con paquetes, shells de desarrollo, configuraciones de NixOS, overlays y más
  • Estructura de ejemplo y objetivos de ejecución

    • En el ejemplo, nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; dentro de inputs significa que se toma la rama nixos-unstable del repositorio NixOS/nixpkgs en GitHub
    • El flake de ejemplo usa supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ]; y nixpkgs.lib.genAttrs para generar salidas para varias arquitecturas de CPU
    • Flakes requiere el nivel packages.<system> y, en el ejemplo, el paquete default bajo packages se define con pkgs.buildGoModule
    • src = ./.; indica que se usa todo el repositorio Git como código fuente
    • devShells define los shells de desarrollo que consulta nix develop; en el ejemplo se usan pkgs.mkShell y buildInputs = with pkgs; [ go gopls gotools ];
  • flake.lock y evaluación pura

    • Cuando se ejecuta un comando de Nix sobre un flake, Nix genera el archivo JSON flake.lock, que fija todos los inputs y los inputs transitivos a revisiones exactas
    • flake.lock es un archivo de bloqueo que permite la reproducibilidad de compilaciones entre distintas máquinas y a lo largo del tiempo
    • Flakes impone evaluación pura, por lo que $NIX_PATH, builtins.currentSystem y las variables de entorno no pueden entrar de forma implícita; todo debe ser explícito
    • Las funciones que cumple Flakes pueden resumirse como: declarar dependencias, fijar dependencias, imponer pureza, ofrecer un esquema estándar de salidas, permitir compartir de forma reproducible y definir entornos de desarrollo

Enfoque equivalente en Guix

  • Guix ya tenía soluciones para buena parte de las funciones de Flakes antes de que Flakes se introdujera en Nix 2.4 el 1 de noviembre de 2021
  • El mecanismo de channels de Guix se introdujo alrededor de 2018-2019
  • La solución de Guix es orthogonal y permite usar cada herramienta de forma independiente, en lugar de adoptar una abstracción monolítica única
  • Channels y declaración de dependencias

    • En Flake, las dependencias se declaran directamente dentro de flake.nix; en el ejemplo se usan nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; y home-manager.url = "github:nix-community/home-manager";
    • inputs.nixpkgs.follows = "nixpkgs"; de un input de Flake hace que home-manager use el nixpkgs del flake actual en lugar de traer su propio input nixpkgs, evitando así que existan dos copias distintas de nixpkgs
    • Los channels de Guix son repositorios Git que incluyen módulos de Guile; normalmente contienen definiciones de paquetes, pero también pueden incluir servicios, configuraciones de sistema y código arbitrario en Scheme
    • Los channels de Guix se declaran en ~/.config/guix/channels.scm, y este archivo Scheme devuelve una lista de registros de channel
    • guix pull obtiene y compila todos los channels, y hace que esos módulos estén disponibles en todos los comandos guix
    • Los channels pueden declarar dependencias sobre otros channels usando el archivo .guix-channel en la raíz del repositorio
    • La dependencia entre channels en Guix es aproximadamente similar a inputs en flake, y al ejecutar guix pull también se obtienen las dependencias transitivas de channels
  • Dependencias por proyecto y dependencias por usuario

    • Flakes sigue un enfoque por proyecto, donde cada repositorio tiene su propio flake.nix y sus inputs, mientras que los channels funcionan a nivel de sistema o por usuario, y channels.scm se aplica a todas las invocaciones de guix
    • Flakes permite de forma natural que distintos proyectos tengan distintos conjuntos de dependencias; en Guix, para lograr el mismo efecto normalmente se usa guix time-machine o perfiles separados
    • Flakes usa una sintaxis tipo URL como github:NixOS/nixpkgs, git+https://..., mientras que los channels usan URLs Git simples
    • La sintaxis de Flake es más ergonómica para referencias rápidas, mientras que los channels son más simples y explícitos
    • Flakes soporta repositorios sin flake.nix como inputs no-flake mediante flake = false;
    • En Guix, como un channel es un repositorio Git que contiene archivos Scheme, no se necesita ningún opt-in especial; cualquier repositorio con módulos de Guile puede ser un channel

Fijación, reproducibilidad y viaje en el tiempo

  • flake.lock

    • flake.lock es un grafo JSON donde todos los inputs quedan fijados con un hash de commit exacto, y Nix verifica narHash, que es el hash del árbol completo de código fuente descargado
    • flake.lock se commitea al repositorio, por lo que quien haga clone obtiene las mismas versiones de dependencias
    • En flake.lock, original es el objetivo solicitado y locked es el objetivo que realmente se obtuvo
    • El sistema de dos capas de flake.lock permite actualizaciones selectivas, como nix flake lock --update-input nixpkgs, manteniendo el resto sin cambios
  • guix describe y guix time-machine

    • Guix registra los commits exactos de todos los channels al ejecutar guix pull, y guix describe muestra esa información
    • La salida de guix describe incluye número de generación, fecha, indicador de actual, nombre del channel, URL del repositorio, rama y commit
    • Los commits de channels registrados en Guix equivalen a un lock file, pero no están en un archivo dentro del directorio del proyecto, sino como un perfil de Guile en ~/.config/guix/current
    • Para compartir un entorno reproducible, en Guix se puede usar guix time-machine
    • guix time-machine --commit=8a1ab328 -- shell -m manifest.scm fija primero Guix a una revisión específica y luego ejecuta guix shell usando las definiciones de paquetes de esa revisión
    • guix time-machine descarga y compila esa revisión si hace falta, y crea un entorno aislado donde las definiciones de paquetes corresponden exactamente al estado de ese commit
    • También existe un patrón en Guix de incluir en el repositorio un channels.scm con commits fijados
    • guix time-machine -C channels.scm -- shell -m manifest.scm reproduce el entorno exacto usando el channels.scm incluido en el repositorio
  • Diferencias entre ambos enfoques

    • flake.lock es por proyecto y automático, mientras que guix describe es por usuario y automático
    • Un channels.scm con commits fijados ofrece fijación por proyecto en Guix, pero de forma manual
    • Guix está mejorando la ergonomía de la fijación por proyecto, pero el flujo de trabajo actual requiere una configuración más explícita
    • flake.lock es un grafo JSON legible por máquina, y su equivalente en Guix es un archivo Scheme que enumera channels con hashes de commit
    • Ambos enfoques logran el objetivo de fijar dependencias, pero el lock de flake está más estructurado porque es un grafo completo de dependencias con entradas original y locked para todos los inputs transitivos
    • guix time-machine es una función sin equivalente directo en flake, ya que permite moverse no solo entre versiones fijadas de dependencias, sino también hacia un estado histórico completamente distinto de la colección de paquetes

Modelo de pureza

  • Flakes se ejecuta en un contexto de evaluación restringido, y el uso de builtins.currentSystem, builtins.getEnv y $NIX_PATH está prohibido o se ignora
  • En Flakes, todo debe venir de las entradas declaradas, lo que dificulta que se generen dependencias accidentales sobre estado implícito
  • La contrapartida de la evaluación pura en Flakes es que se necesitan parámetros system explícitos en muchos lugares para detectar el sistema, y no es posible leer variables de entorno
  • Cuando se necesita una vía de escape impura en Flakes, se debe pasar explícitamente --impure
  • Guix no necesita un modo de evaluación pura aparte, ya que por convención la evaluación ya es pura
  • Los módulos de Guile no acceden a variables de entorno a menos que se les pasen explícitamente
  • En Guix no existe un equivalente a $NIX_PATH, y los paquetes se resuelven mediante el sistema de módulos, no por una ruta de búsqueda
  • En Guix no existe un concepto equivalente a builtins.currentSystem, y los sistemas se especifican explícitamente mediante los metadatos del paquete y la bandera --system
  • Las compilaciones en Guix también son puras, y se ejecutan en contenedores aislados donde solo son visibles las entradas declaradas explícitamente
  • En las compilaciones de Guix no hay acceso a /usr/bin, /etc ni a la red; las excepciones de acceso a red se limitan a derivations de salida fija
  • El método de aislamiento de compilación de Nix y Guix comparte esencialmente el mismo enfoque
  • Guix logra la pureza a nivel de arquitectura mediante la estructura de módulos de Scheme, mientras que Flakes impone la pureza superponiendo un modo de evaluación restringido sobre un sistema originalmente impuro

Esquema de salidas y modelo de datos

  • Esquema de salidas de Flake

    • Flakes define un esquema estándar para las salidas, y packages.<system>.<name> se usa en nix build, devShells.<system>.<name> en nix develop y apps.<system>.<name> en nix run
    • El esquema de salidas de Flake también incluye nixosConfigurations.<name>, overlays.<name>, nixosModules.<name>, formatter.<system>, templates.<name> y checks.<system>.<name>
    • La estandarización del esquema de salidas de Flake hace que nix build ., nix run y nix flake show consulten ubicaciones consistentes, lo que mejora la capacidad de descubrimiento
    • La desventaja del esquema de salidas de Flake es que es rígido; para agregar tipos de salida arbitrarios se necesita modificar el propio Nix, aunque existe un pequeño mecanismo de extensión
    • Debido al parámetro <system> de Flake, el soporte multiplataforma debe manejarse explícitamente, por lo que se usan funciones auxiliares o bibliotecas como forAllSystems, flake-utils y flake-parts
  • Tipos de datos de primera clase en Guix

    • En Guix no hay un único esquema de salidas como en Flakes, sino tipos de datos de primera clase que pueden ser consumidos por varios comandos
    • En Guix, los paquetes se definen como registros <package> y los usan guix install y guix build
    • En Guix, los manifests se definen como archivos de Scheme y los usan guix shell -m y guix package
    • En Guix, las configuraciones de sistema se definen con operating-system y las usa guix system reconfigure
    • En Guix, las configuraciones de home se definen con home-environment y las usa guix home reconfigure
    • En Guix, los servicios se definen como registros <service> y se usa el campo services de operating-system
    • En Guix, los channels son repositorios Git y los usa guix pull
    • En Guix, las variantes de paquetes son procedimientos de Scheme y se usan --with-input y --transform
  • Archivos y definiciones de paquetes

    • Un proyecto de Guix puede ofrecer una combinación de un channel con definiciones de paquetes, manifest.scm para desarrollo, system.scm para despliegue y declaraciones operating-system o home-environment, entre otros
    • En Guix, estos archivos no requieren un archivo especial de punto de entrada; son simplemente archivos de Scheme que definen valores de Scheme
    • En Guix, basta con especificar el archivo al subcomando guix correspondiente para que el comando lo procese, sin necesidad de ceremonias adicionales ni validación de esquema
    • Un ejemplo de manifest.scm declara un entorno de desarrollo pasando una lista de nombres de paquetes "guile", "guile-git" y "guile-json" a specifications->manifest
    • Un ejemplo de mylib.scm define un registro <package>, el equivalente en Guix a una derivation de Nix, y los campos del paquete pueden consultarse de forma programática
    • Un ejemplo de definición de paquete incluye (name "mylib"), (version "0.1.0"), (source (local-file ".")), (build-system gnu-build-system), (inputs (list guile guile-git)), (home-page "https://example.com";) y (license gpl3+)
    • local-file en Guix toma los archivos del directorio actual en tiempo de compilación, de forma similar a src = ./.; en Nix
    • gnu-build-system en Guix sigue el método ./configure && make && make install, y Guix también tiene otros sistemas de compilación como cmake-build-system y python-build-system
    • A diferencia de Nix, donde stdenv proporciona implícitamente gcc y coreutils, en Guix todas las dependencias son explícitas

Entorno de desarrollo

  • En el ejemplo de devShells de Flakes se usa devShells.x86_64-linux.default = pkgs.mkShell { buildInputs = with pkgs; [ go gopls gotools ]; shellHook = '' echo "Welcome to the devShell!" ''; };
  • mkShell crea una derivation que genera un entorno de shell durante la build; buildInputs entra en el PATH dentro del shell y shellHook ejecuta bash arbitrario al entrar al shell
  • Se entra al dev shell de Flake con nix develop o con nix develop .#my-shell para un shell con nombre
  • El entorno de desarrollo de Guix puede definirse en manifest.scm pasando una lista de cadenas de especificación de paquetes a specifications->manifest
  • El manifest de Guix del ejemplo declara "go", "gopls", "go-tools"
  • Se entra al shell basado en manifest de Guix con guix shell -m manifest.scm
  • Guix permite, en un entorno ad hoc, pasar solo nombres de paquetes por línea de comandos sin archivo, como guix shell go gopls go-tools
  • guix shell soporta --container para aislamiento total, --emulate-fhs para ejecutar programas que esperan el layout estándar del filesystem de Linux y --nesting para ejecutar Guix dentro de un contenedor de Guix
  • Los manifests de Guix son archivos Scheme independientes, no incrustados dentro de una estructura mayor como flake.nix
  • guix shell puede funcionar incluso sin archivo, pero nix develop requiere un flake o un shell.nix de la interfaz legacy
  • Flakes ofrece dev shells con nombre como devShells.x86_64-linux.test, devShells.x86_64-linux.default
  • En lugar de dev shells con nombre, los manifests de Guix se organizan poniendo archivos separados como manifest.scm, test-manifest.scm uno junto a otro
  • Tanto Nix Flakes como Guix soportan desarrollo en contenedores

Configuración del sistema

  • NixOS y Flakes

    • En el ejemplo de nixosConfigurations de Flakes, nixpkgs.lib.nixosSystem recibe una lista de módulos de NixOS y genera una derivation completa del sistema que incluye kernel, servicios, archivos de configuración, etc.
    • El comando de ejemplo para desplegar NixOS basado en Flake es nixos-rebuild switch --flake .#myhost
    • El ejemplo nixosConfigurations.myhost incluye system = "x86_64-linux"; y modules = [ ./configuration.nix home-manager.nixosModules.home-manager ];
    • Los módulos de NixOS usan un sistema de módulos con fusión basada en prioridades mediante options, config, mkIf, mkDefault, mkForce
    • En el sistema de módulos de NixOS, aunque varios módulos configuren la misma opción, el sistema resuelve las prioridades, por lo que es fácil evitar conflictos incluso cuando decenas de módulos contribuyen a la misma configuración
  • Guix operating-system

    • El operating-system de Guix no es una función sino un record de Scheme, y Guix valida cada field como un valor tipado con nombre
    • El comando de ejemplo para desplegar un sistema con Guix es guix system reconfigure config.scm
    • El record operating-system del ejemplo incluye (host-name "myhost"), (timezone "Etc/UTC"), configuración del bootloader, filesystems y servicios
    • El ejemplo de configuración del bootloader en Guix usa grub-efi-bootloader y el destino "/boot/efi", y Guix soporta GRUB, U-Boot, etc.
    • Los filesystems en Guix se declaran como una lista, y %base-file-systems proporciona valores por defecto para /dev, /proc, /sys, etc.
    • Los servicios en Guix forman un directed acyclic graph (DAG), y cada servicio puede extender otros servicios
    • %base-services proporciona servicios esenciales como el sistema init Shepherd, syslog, networking, etc.
    • La configuración del sistema en Guix no requiere un tipo especial de output; basta con indicar a guix system un archivo que retorne un record operating-system
    • La composición de servicios de Guix facilita escribir servicios nuevos que se conecten al sistema existente de manera arbitraria

Descubribilidad y registro

  • Flakes tiene flake.nix, un punto de entrada estándar donde se declaran en un solo archivo las dependencias del proyecto, outputs y un esquema descubrible
  • Los proyectos de Guix pueden usar archivos basados en convención como manifest.scm, channels.scm, guix.scm, package.scm
  • Hay intentos de estandarizar guix.scm como archivo de proyecto reconocido automáticamente por guix shell, pero todavía no está tan establecido como flake.nix
  • Flakes tiene el registro global flake-registry, que mapea nombres cortos a URL; los ejemplos son nix run nixpkgs#hello, nix build github:NixOS/nixpkgs#firefox
  • Guix usa especificaciones de paquetes para una conveniencia similar; los ejemplos son guix shell hello, guix install firefox
  • Guix no tiene un equivalente de registro para apuntar a un repositorio Git arbitrario mediante un nombre corto, y usa la URL directamente
  • El registro de Nix a veces ha sido una fuente de confusión, porque no siempre está claro si nixpkgs es una entrada del registro, una ruta local u otro destino
  • nix flake show es un comando que muestra en vista de árbol todo lo que ofrece un flake
  • Guix tiene guix search para paquetes y guix system search para servicios, pero no existe un comando equivalente que muestre todo lo que ofrece un proyecto o repositorio específico, por lo que hay que revisar directamente los archivos Scheme
  • Flakes tiene una fuerte capacidad de descubribilidad en el sentido de que nix flake show ofrece una vista consistente de lo que proporciona un proyecto
  • Los proyectos de Guix son más ad hoc, hay que saber qué archivo mirar y no existe un archivo estándar de punto de entrada único
  • Guix tiene gran flexibilidad porque todo es Scheme, así que se puede definir y combinar lo que se quiera sin un schema

Modelo de paquetes y reescritura de grafos

  • En Nix, un paquete es una función que devuelve una derivation mediante una llamada a stdenv.mkDerivation { ... }, y el resultado es un conjunto de atributos opaco.
  • En Guix, un paquete es un registro <package>, una estructura de datos transparente con campos nombrados que puede inspeccionarse, transformarse y combinarse con procedimientos estándar de Scheme.
  • Como las definiciones de paquetes en Guix son registros transparentes y no funciones opacas, es posible inspeccionarlas y transformarlas de forma programática sin herramientas especiales.
  • En Guix, como los paquetes son datos, las reescrituras de grafos se pueden realizar fácilmente.
  • En Guix, con package-input-rewriting se puede expresar una operación que recorra todo el grafo de dependencias para reemplazar perl por perl-minimal.
  • La palabra clave inherit de Guix redefine un paquete heredando todos los campos de coreutils y sobrescribiendo solo los campos especificados.
  • Nix tiene overlays con un propósito similar, pero debido a su interfaz de funciones opaca, inspeccionar y transformar es más difícil y su usabilidad es menor.

Actualizaciones de seguridad, bootstrap y autenticación

  • El grafting de Guix permite aplicar actualizaciones de seguridad en el árbol de dependencias sin reconstruir todos los paquetes dependientes.
  • Cuando hay una vulnerabilidad en bibliotecas de bajo nivel como glibc, Guix puede reescribir las rutas del almacén para sustituirlas por la versión corregida.
  • Nix reconstruye todo en escenarios de actualizaciones de seguridad, y en árboles de dependencias grandes el tiempo de compilación puede diferir por horas.
  • Guix pone un fuerte énfasis en el bootstrap basado en código fuente, de modo que todo el sistema puede construirse a partir de una base mínima de confianza.
  • La cadena de bootstrap de Guix comienza con un ensamblador hexadecimal de alrededor de 500 bytes y continúa con el compilador de C mes escrito en Scheme, tcc y toda la toolchain de GNU.
  • El proyecto bootstrappable builds aborda los detalles completos del bootstrap desde código fuente.
  • Nix depende de más semillas binarias que Guix.
  • Si no se puede auditar la cadena de bootstrap, no es posible verificar por completo que el sistema realmente se haya construido a partir del código fuente previsto, por lo que el bootstrap completo desde código fuente es importante para la confianza y la verificabilidad.
  • Los canales de Guix admiten autenticación criptográfica de forma predeterminada.
  • Un canal de Guix especifica una “introducción” compuesta por un commit concreto y su firma Ed25519, y Guix verifica toda la cadena de firmas desde esa introducción hasta el commit actual.
  • Flakes usa HTTPS y la infraestructura de GitHub como modelo de confianza, lo que representa un modelo de seguridad distinto de la autenticación de canales con Ed25519 en Guix.

Correspondencias clave del cuadro resumen

  • En la declaración de dependencias, Flakes usa inputs en flake.nix, mientras que Guix usa channels.scm y .guix-channel.
  • Para fijar dependencias, Flakes usa flake.lock automático y por proyecto, mientras que Guix usa guix describe automático por usuario y channels.scm con commits especificados manualmente por proyecto.
  • La evaluación pura se aplica en el modo flake y, en Guix, es una característica inherente por diseño.
  • En el esquema de salidas, Flakes usa un attrset estructurado en outputs, mientras que Guix usa registros de Scheme ad hoc.
  • Para entornos de desarrollo, Flakes usa devShells y nix develop, mientras que Guix usa manifest.scm y guix shell.
  • En la configuración del sistema, Flakes usa nixosConfigurations y el sistema de módulos, mientras que Guix usa operating-system y un DAG de servicios.
  • Para reproducibilidad con un solo comando, Flakes usa nix build github:foo/bar, mientras que Guix usa la forma guix time-machine -C channels.scm -- build.
  • Para fijación por proyecto, Flakes lo maneja automáticamente con flake.lock, mientras que Guix lo hace manualmente con channels.scm que incluye commits.
  • En explorabilidad, Flakes usa nix flake show, mientras que Guix depende de la inspección de módulos de Scheme.
  • En el modelo de paquetes, Flakes/Nix usa funciones opacas y Guix usa registros transparentes.
  • En el sistema init, Nix usa systemd y Guix usa GNU Shepherd.
  • Para actualizaciones de seguridad, Nix requiere reconstrucción completa y Guix usa grafting rápido.
  • En confianza de bootstrap, Nix se basa en semillas binarias y Guix en bootstrap completo desde código fuente.
  • Para actualizaciones autenticadas, Flakes usa confianza en HTTPS/GitHub y Guix usa autenticación de canales con Ed25519.
  • En soporte FHS, Nix ofrece buildFHSUserEnv y Guix --emulate-fhs.
  • En soporte no Linux, Nix cuenta con nix-darwin para macOS y Guix se organiza alrededor de GNU Hurd.
  • En cuanto a si es exclusivamente software libre, Nix no lo es y es configurable, mientras que Guix cumple con la FSDG.

Conclusión

  • Flakes y Guix resuelven el mismo tipo de problemas —reproducibilidad, gestión de dependencias y declaración del sistema— con filosofías arquitectónicas distintas.
  • Flakes se acerca a una sola funcionalidad con un archivo, un esquema, un archivo de bloqueo y un conjunto de convenciones.
  • Guix es una combinación de herramientas ortogonales como channels para la distribución, manifests para los entornos, operating-system para la configuración, guix time-machine para la reproducibilidad y registros de Scheme para otras estructuras.
  • Si prefieres una sola forma estándar, un solo archivo de entrada, un solo esquema de salida y un solo formato de bloqueo, Flakes encaja de manera natural.
  • Si prefieres aplicar a la gestión de paquetes la filosofía Unix de combinar herramientas pequeñas e independientes para que cada una haga bien una sola cosa, Guix encaja mejor.
  • Ambos ecosistemas han evolucionado en torno a la idea de que la gestión de paquetes debe ser funcional, declarativa y reproducible, y empujan esa misma idea con implementaciones diferentes.

1 comentarios

 
GN⁺ 5 시간 전
Opiniones en Lobste.rs
  • Este sitio es demasiado frustrante de leer en móvil: la letra es un poco pequeña y además interrumpe constantemente al hacer scroll.
    Después de la primera comparación ya no pude seguir leyendo, porque me regresaba de golpe al índice todo el tiempo.

    • De plano no se puede leer. Se mueve como un yoyó. Era uno de los artículos que más quería leer últimamente, así que me decepcionó por ser una experiencia de lectura increíblemente frustrante.
    • En escritorio pasa lo mismo. Es absurdo y parece como si hubieran roto la accesibilidad a propósito.
  • Incluso después de leer el artículo, todavía no me queda claro cómo se deben declarar y fijar las dependencias de un proyecto. Da la impresión de que, para distribuirlo y compartirlo, hay que buscar manualmente en channels.scm el hash de commit de cada dependencia transitiva e insertarlo ahí.
    time-machine parece funcionar solo con el conjunto de paquetes de Guix, no con dependencias fuera del árbol.
    También es bastante fácil ejecutar código viejo de nixpkgs, algo como nix run github:nixos/nixpkgs/<commit hash>#<package>.
    Lo particular de Guix es que no separa la versión del conjunto de paquetes de la versión del gestor de paquetes. Si quieres ejecutar paquetes antiguos, también terminas ejecutando una versión antigua de Guix, y no me queda claro por qué querrías eso.
    El artículo dice que en flakes hay que buscar y fijar commits manualmente, pero justo después pone como ejemplo un comando de Guix en el que también hay que especificar un commit. En Nix flakes también puedes sobrescribir la versión de nixpkgs con --override-input, aunque es medio sucio, y justo eso es una de las cosas que unflake intenta mejorar.

    • Tengo menos experiencia usando Guix que el autor, pero sí he leído algo de la documentación, así que intentaré responder algunas cosas.
      Normalmente desarrollas dentro de un entorno dedicado de guix shell, y cuando llega el momento de compartirlo, usas guix describe -f channels > channels.scm para registrar todos los hashes de commit en channels.scm.
      Si ves la documentación de declaring channel dependencies, parece que sí puedes especificar los commits de las dependencias, pero no veo una opción para verificar que, si esa dependencia a su vez tiene dependencias, esas también queden fijadas a commits específicos.
      La sintaxis --commit= de time-machine aplica a canales de Guix, pero con -C también puedes cargar canales adicionales desde un archivo.
      Incluso si hay cambios incompatibles en el gestor de paquetes y en los registros de paquetes, esto tiene la ventaja de no perder historial ni reproducibilidad.
    • También se podría lograr construyendo un índice inverso de nixpkgs: algo como que desde el commit X hasta el Y de nixpkgs está incluida la versión A de cierto paquete.
      Eso sí, requiere hacer un checkout de nixpkgs por cada commit, así que el costo inicial de construirlo sería enorme. Una vez hecho, mantener el índice debería costar poco.
  • Ya le avisaron a coopi del problema del sitio y de este hilo, así que ojalá lo arreglen pronto.
    Hablando desde alguien que está completamente inclinado hacia Guix, también me gustaría, como dijo coopi, que Guix tuviera un archivo/directorio estándar como flake.nix o un directorio nix donde estuviera todo. Aunque quizá no sea posible, porque para importar módulos de Scheme hay que indicar la ruta correcta.
    En este post de Lobsters están las cosas de las que habla el autor, así que parece que con las etiquetas nix y lisp basta.

    • No me convence quitar linux. Es el único kernel que ambos tienen en común :P Aunque sí, como dijiste, puede que unix no encaje.
    • También estaría bien tener un tipo de dato de canal estructurado que ayudara a inferir automáticamente qué ofrece un canal, como hacen las flakes.
      Por ejemplo, algo así:
      (channel  
        (operating-systems  
          (list my-vm))  
        (services  
          (list my-system-service)))  
      
      Y también estaría bien un comando guix channel que ayudara a crear y manejar canales nuevos.
  • Me pregunto si en Guix existe una función como .inputs.nixpkgs.follows de Nix flakes para sobrescribir los valores fijados de dependencias transitivas.
    Además, buena parte de la explicación del autor sobre Guix me recuerda al Nix anterior a flakes: sin un punto de entrada estándar y con una estructura basada en canales. Pero en Guix, como hay un sistema de tipos y un lenguaje real, siento que ese mismo patrón duele menos. Se siente como una historia alternativa de lo que Nix habría sido si hubiera sido mejor o hubiera usado otro lenguaje.

    • ¿Y para qué se usa esa función?
  • Por los problemas de usabilidad que señalaron otros comentarios, me da cosa recomendarlo. Yo no me había dado cuenta porque uso NoScript y desactivo JavaScript por defecto.
    Aun así, este artículo me cayó justo en el momento indicado. En mi empresa estamos avanzando mucho hacia usar Nix y las flakes nos han dado algo de batalla, pero la explicación de este artículo me pareció mucho más clara que otras que había leído antes.

    • Según Coopi, intentaron seguir el principio de mejora progresiva para que pudiera leerse incluso sin JavaScript ni CSS; con JavaScript sí la regaron, pero al menos esa filosofía había estado funcionando. Dice que ya deberían haber arreglado la parte de JavaScript.
  • Respuesta de Coopi: hizo un cambio esta mañana, pero no pudo probarlo por trabajo, y al parecer resultó que había un problema con JavaScript.

  • Este sitio no se puede usar en iOS móvil. La página parece cargar desde abajo y luego desplazarse inmediatamente hacia arriba, y si bajo más de una pantalla, algo se activa y me vuelve a subir.
    El modo de lectura sí funciona, pero se pierden el resaltado y los detalles de estilo originales, que en realidad estaban bastante bien.

  • Es válido decir que lo que hacen las flakes también se puede hacer con varias herramientas de Guix, pero hay que señalar que en Nix también existían antes, y siguen existiendo, herramientas pequeñas y ortogonales para resolver esos mismos problemas.
    Lo que aportan las flakes es un punto de entrada estándar para proyectos y el ecosistema que eso hace posible, por ejemplo el registro. El artículo mismo dice que Guix no tiene esa parte.
    Los usuarios de Guix pueden decidir que no necesitan un punto de entrada estándar, y muchos usuarios de Nix también lo han decidido durante mucho tiempo.
    Pero decir que puedes lograr flakes con un conjunto de herramientas ortogonales suena un poco como afirmar que FreeBSD no necesita soporte OCI porque con jail ya puedes hacer todo lo necesario. Se pierde de vista la parte en la que la estandarización habilita un ecosistema.
    Me interesa mucho Guix y hasta he contribuido un poco, pero sí me gustaría comparar por qué compilar con guix time-machine junto con channels.scm tarda tanto más que cambiar los valores fijados de una flake y evaluar Nix. Si fuera algo como 3 veces más lento, por ejemplo pasar de 5~10 segundos a 15~30 segundos, me parecería aceptable, pero cuando lo intenté, ni de lejos era solo eso.