¿Cómo hacer un proyecto de Haskell cabal con biblioteca + ejecutables que todavía se ejecutan con runhaskell / ghci?
Si declara una biblioteca + secciones ejecutables en un archivo cabal mientras evita la doble compilación de la biblioteca poniendo la biblioteca en un directorio hs-source-dirs
, normalmente ya no puede ejecutar su proyecto con ghci
y runhaskell
, especialmente si los ejecutables tienen módulos auxiliares.
¿Qué es un diseño de proyecto recomendado que
- solo construye lo que se necesita una vez
- permite usar
runhaskell
- tiene una estructura limpia sin hacks?
2 answers
Supongamos que tiene una biblioteca mylib
, y ejecutables mylib-commandline
y mylib-server
.
Se usa hs-source-dirs
para la biblioteca y cada ejecutable para que cada uno tenga su propia raíz de proyecto, evitando la doble compilación:
mylib/ # Project root
mylib.cabal
src/ # Root for the library
tests/
mylib-commandline/ # Root for the command line utility + helper modules
mylib-server/ # Root for the web service + helper modules
Disposición del directorio completo:
mylib/ # Project root
mylib.cabal
src/ # Root for the library
Web/
Mylib.hs # Main library module
Mylib/
ModuleA # Mylib.ModuleA
ModuleB # Mylib.ModuleB
tests/
...
mylib-commandline/ # Root for the command line utility
Main.hs # "module Main where" stub with "main = Web.Mylib.Commandline.Main.main"
Web/
Mylib/
Commandline/
Main.hs # CLI entry point
Arguments.hs # Programm command line arguments parser
mylib-server/ # Root for the web service
Server.hs # "module Main where" stub with "main = Web.Mylib.Server.Main.main"
Web/
Mylib/
Server/
Main.hs # Server entry point
Arguments.hs # Server command line arguments parser
El archivo de punto de entrada similar a un trozo mylib-commandline/Main.hs
se ve así:
module Main where
import qualified Web.Mylib.Server.Main as MylibServer
main :: IO ()
main = MylibServer.main
Los necesita porque un executable
debe comenzar en un módulo simplemente llamado Main
.
Su mylib.cabal
parece esto:
library
hs-source-dirs: src
exposed-modules:
Web.Mylib
Web.Mylib.ModuleA
Web.Mylib.ModuleB
build-depends:
base >= 4 && <= 5
, [other dependencies of the library]
executable mylib-commandline
hs-source-dirs: mylib-commandline
main-is: Main.hs
other-modules:
Web.Mylib.Commandline.Main
Web.Mylib.Commandline.Arguments
build-depends:
base >= 4 && <= 5
, mylib
, [other depencencies for the CLI]
executable mylib-server
hs-source-dirs: mylib-server
main-is: Server.hs
other-modules:
Web.Mylib.Server.Main
build-depends:
base >= 4 && <= 5
, mylib
, warp >= X.X
, [other dependencies for the server]
cabal build
construirá la biblioteca y los dos ejecutables sin doble compilación de la biblioteca, porque cada uno está en su propio hs-source-dirs
y los ejecutables dependen de la biblioteca.
Todavía puede ejecutar los ejecutables con runghc
desde la raíz de su proyecto, usando el interruptor -i
para indicar dónde buscará los módulos (usando :
como separador):
runhaskell -isrc:mylib-commandline mylib-commandline/Main.hs
runhaskell -isrc:mylib-server mylib-server/Server.hs
De esta manera, puede tener un diseño limpio, ejecutables con módulos auxiliares, y todo sigue funcionando con runhaskell
/runghc
y ghci
. Para evitar escribir esta bandera repetidamente, puede agregar algo similar a
:set -isrc:mylib-commandline:mylib-server
A su archivo .ghci
.
Tenga en cuenta que a veces debería dividir su código en paquetes separados, p.ej. mylib
, mylib-commandline
y mylib-server
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-06 21:07:07
Puede usar cabal repl
para iniciar ghci con la configuración del archivo cabal y cabal run
para compilar y ejecutar los ejecutables. A diferencia de runhaskell
y ghci
, usar cabal repl
y cabal run
también recoge las dependencias de las cajas de arena de cabal correctamente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-19 08:10:53