Pregunta Cómo hacer que Cabal y nix trabajen juntos


Por lo que yo entendí, Nada es una alternativa para caja de arena de cabal. Finalmente logré instalar Nix, pero todavía no entiendo cómo puede reemplazar un sandbox.

Entiendo que no necesites a cabal con Nix y la versión envuelta de GHC; Sin embargo, si quieres para publicar un paquete necesitarás en algún momento empaquetarlo usando cabal. Por lo tanto, debe poder escribir y probar su configuración de cabal en NIX. ¿Cómo haces eso?

Idealmente, me gustaría un entorno similar a la arena de cabal, pero "contenido" dentro de NIX, ¿es posible? De hecho, lo que realmente me gustaría es el equivalente de sandboxes anidados, ya que normalmente trabajo en proyectos formados por varios paquetes.

Actualización sobre mi flujo de trabajo actual

En este momento trabajo en 2 o 3 proyectos independientes (P1, P2, P3) que están compuestos cada uno por 2 o 3 módulos / paquetes cabal, digamos por P1: L11, L12 (bibliotecas)  y E11 (ejecutables). E11 depende de L12 que depende de L11. Principalmente dividí los ejecutables de la biblioteca porque son privados y se mantienen en un repositorio privado de git.

En teoría, cada proyecto podría tener esta propia caja de arena (compartida entre sus submódulos). Intenté eso (tener un sandbox común para L11 L12 y E11), pero es rápidamente molesto porque, si modifica L11, no puede reconstruirlo porque E11 depende de él, así que tengo que desinstalar E11 primero para recompilar L11. Puede que no sea exactamente el caso, pero encuentro el problema similar. Esto estaría bien si ocasionalmente modificara L11, pero en la práctica, lo cambié más que E11.

Como el sandbox compartido no funciona, volví al único sandbox para cada solución de paquete. Está funcionando, pero es menos que ideal. El principal problema es si modifico L11, necesito compilarlo dos veces (una vez en L11, y luego otra vez en E11). Además, cada vez que empiezo una nueva zona de pruebas, como todos saben, necesito esperar un poco para que todo el paquete se descargue y vuelva a compilar.

Así que al usar Nix, estoy esperando poder configurar "ambientes" separados por proyecto, lo que resuelve todo el problema.

Espero que esto sea más claro.


32
2018-01-15 17:04


origen


Respuestas:


Hago todo mi desarrollo usando Nix y Cabal estos días, y puedo decir felizmente que trabajan en armonía muy bien. Mi flujo de trabajo actual es muy nuevo, ya que depende de las características de nixpkgs que acaba de llegar a la rama principal. Como tal, lo primero que debes hacer es clonar nixpkgs de Github:

cd ~
git clone git://github.com/nixos/nixpkgs

(En el futuro, esto no será necesario, pero ahora mismo lo es).

Uso de un solo proyecto

Ahora que tenemos un nixpkgs clonar, podemos comenzar a usar el haskellng conjunto de paquetes. haskellng es una reescritura de cómo empaquetamos cosas en Nix, y nos interesa por ser más predecibles (los nombres de paquetes coinciden con los nombres de paquetes de Hackage) y más configurables. Primero, instalaremos el cabal2nix herramienta, que puede automatizar algunas cosas para nosotros, y también vamos a instalar cabal-install para proporcionar el cabalejecutable:

nix-env -f ~/nixpkgs -i -A haskellngPackages.cabal2nix -A haskellngPackages.cabal-install

A partir de este punto, todo está bastante claro.

Si está comenzando un nuevo proyecto, puede simplemente llamar cabal init en un nuevo directorio, como lo haría normalmente. Cuando esté listo para construir, puede convertir esto .cabal archivo en un entorno de desarrollo:

cabal init
# answer the questions
cabal2nix --shell my-project.cabal > shell.nix

Esto te da una shell.nix archivo, que se puede usar con nix-shell. Sin embargo, no es necesario que use esto muy a menudo, el único momento en que generalmente lo usará es con cabal configure:

nix-shell -I ~ --command 'cabal configure'

cabal configure almacena en caché rutas absolutas para todo, así que ahora cuando quieras construir simplemente usa cabal build como normal:

cabal build

Siempre que tu .cabal cambios en el archivo que necesitarás regenerar shell.nix - simplemente ejecute el comando de arriba, y luego cabal configure después.

Uso múltiple del proyecto

El enfoque se adapta muy bien a múltiples proyectos, pero requiere un poco más de trabajo manual para "pegar" todo junto. Para demostrar cómo funciona esto, consideremos mi socket-io biblioteca. Esta biblioteca depende de engine-io, y generalmente desarrollo ambos al mismo tiempo.

El primer paso para Nix: imaginar este proyecto es generar default.nix expresiones junto a cada individuo .cabal archivo:

cabal2nix engine-io/engine-io.cabal > engine-io/default.nix
cabal2nix socket-io/socket-io.cabal > socket-io/default.nix

Estas default.nix las expresiones son funciones, entonces no podemos hacer mucho ahora. Para llamar a las funciones, escribimos las nuestras shell.nix archivo que explica cómo combinar todo. por engine-io/shell.nix, no tenemos que hacer nada particularmente inteligente:

with (import <nixpkgs> {}).pkgs;
(haskellngPackages.callPackage ./. {}).env

por socket-io, tenemos que depender de engine-io:

with (import <nixpkgs> {}).pkgs;
let modifiedHaskellPackages = haskellngPackages.override {
      overrides = self: super: {
        engine-io = self.callPackage ../engine-io {};
        socket-io = self.callPackage ./. {};
      };
    };
in modifiedHaskellPackages.socket-io.env

Ahora tenemos shell.nix en cada entorno, para que podamos usar cabal configure como antes.

La observación clave aquí es que cada vez que engine-io cambios, necesitamos reconfigurar socket-io para detectar estos cambios Esto es tan simple como correr

cd socket-io; nix-shell -I ~ --command 'cabal configure'

Nix notará que ../engine-io ha cambiado, y reconstruirlo antes de ejecutar cabal configure.


46
2018-01-15 18:43