haskell - program - instalar cabal
¿Cómo reducir la duplicación en los campos dependientes de la compilación de un archivo.cabal? (4)
Aquí hay un archivo .cabal:
Name: myprogram
Version: 0.1
-- blah blah blah
Cabal-version: >=1.9.2
Executable myprogram
HS-source-dirs: src
Main-is: Main.hs
Build-depends: attoparsec == 0.10.*,
base == 4.3.*,
-- long long list of packages
Test-Suite test
HS-source-dirs: test, src
Type: exitcode-stdio-1.0
Main-is: Main.hs
Build-depends: attoparsec == 0.10.*,
base == 4.3.*,
-- long long list of packages
QuickCheck == 2.4.*
¿Hay alguna manera de que pueda reemplazar la larga lista de paquetes dependientes de la compilación para el conjunto de pruebas con "lo mismo que para el ejecutable, más QuickCheck"?
Editar: información de la versión.
- cabal-dev 0.9
- cabal-install 0.10.2
- Librería de Cabal 1.10.2.0
- GHC 7.0.4
- Plataforma Haskell 2011.4.0.0
¿Hay alguna manera de que pueda reemplazar la larga lista de paquetes dependientes de la compilación para el conjunto de pruebas con "lo mismo que para el ejecutable, más QuickCheck"?
No que yo sepa. Sin embargo, hay una forma de mencionar solo la lista de paquetes de acuerdo con la build-depends
una vez, estructurando su proyecto en tres objetivos:
- una biblioteca que contiene todo su código y necesita la larga lista de dependencias de compilación.
- un archivo ejecutable que consta de un solo archivo y depende de la base y la biblioteca desde arriba.
- un conjunto de pruebas que depende de la biblioteca desde arriba y de los paquetes de prueba que está utilizando.
Tal vez este enfoque es lo que la respuesta de Indygemma propone, pero el archivo Cabal propuesto no lo logrará del todo, como señala Norman Ramsey en un comentario. Estos son los puntos principales de lo que necesita en un archivo Cabal. Para ver un ejemplo completo que funciona para mí, puedes mirar este archivo Cabal .
name: my-program
version: ...
library
hs-source-dirs: src-lib
build-depends: base, containers, ...
exposed-modules: My.Program.Main, ...
executable my-program
hs-source-dirs: src-exec
main-is: my-program.hs
Build-depends: base, my-program
test-suite tests
type: exitcode-stdio-1.0
hs-source-dirs: src-test
main-is: tests.hs
other-modules: ...
build-depends: base, my-program, test-framework, ...
Puntos importantes:
Hay tres directorios de origen separados para los tres objetivos. Esto es necesario para evitar que GHC vuelva a compilar los archivos de la biblioteca al construir los otros objetivos.
Todo el código de la aplicación está en la biblioteca. El ejecutable es solo un contenedor, como este:
import My.Program.Main (realMain) main = realMain
La biblioteca expone todos los módulos que son necesarios para la prueba.
El último punto destaca el inconveniente de este enfoque: termina teniendo que exponer los módulos internos. El principal beneficio de este enfoque es que tiene menos duplicación en el archivo Cabal y, quizás más importante, menos duplicación en el proceso de compilación: el código de la biblioteca se compilará solo una vez y luego se vinculará con el ejecutable y el conjunto de pruebas. .
Hay una sección de biblioteca opcional para archivos .cabal, que resuelve su problema.
name: myprogram
version: 0.1
-- blah blah blah
cabal-version: >=1.9.2
library
build-depends: attoparsec == 0.10.*
, base == 4.3.*
-- long long list of packages
executable myprogram
hs-source-dirs: src
main-is: Main.hs
test-suite test
hs-source-dirs: test, src
type: exitcode-stdio-1.0
main-is: Main.hs
build-depends: QuickCheck == 2.4.*
No es una manera fácil:
puedes usar m4 y especificar tus dependencias una vez, pero luego necesitarás volver a procesar tu archivo Cabal a través de m4 cada vez que lo cambies.
puede mover el código que está probando a una biblioteca, y luego especificar la biblioteca en su Build-depends para la prueba. Eso requiere que instale una biblioteca incluso para ejecutar la prueba.
Simplemente no puedes poner la prueba en el archivo cabal. Compilarlo con ghc --make, que generará dependencias. Pero luego pierdes la integración cabal.
También podría considerar usar hpack lugar de escribir el archivo .cabal a mano:
En el formato package.yaml de hpack, puede especificar un campo de dependencies
común cuyas entradas se agreguen al campo de dependencies
de cada componente al generar el archivo .cabal.
Por ejemplo, vea el propio package.yaml hpack.cabal y el hpack.cabal generado.
Para comenzar a usar hpack con un paquete existente, puede usar hpack-convert que generará el paquete.yaml de un archivo existente .cabal.
Para crear un nuevo paquete que use hpack, puede usar la plantilla simple-hpack
la pila de la simple-hpack
manera: stack new mypkg simple-hpack
.
Si usa stack para el desarrollo, no tiene que llamar a hpack
manualmente para regenerar el archivo .cabal desde un paquete actualizado.yaml - stack lo hará automáticamente.