54 votes

Comment faire un projet Haskell cabal avec bibliothèque + exécutables qui fonctionnent toujours avec runhaskell / ghci?

Si vous déclarez une bibliothèque + exécutable sections dans une cabale de fichier tout en évitant la double compilation de la bibliothèque en mettant la bibliothèque en hs-source-dirs annuaire, vous ne pouvez pas généralement de exécuter votre projet avec ghci et runhaskell plus, surtout si les exécutables ont helper modules eux-mêmes.

Qu'est ce qu'un projet recommandé la mise en page que

  • s'appuie uniquement ce qui est nécessaire une fois
  • permet d'utiliser l' runhaskell
  • a une structure propre sans hacks?

86voto

nh2 Points 4421

Supposons que vous avez un mylib bibliothèque et, mylib-commandline et mylib-server exécutables.

Vous utilisez hs-source-dirs pour la bibliothèque et chaque fichier exécutable afin que chacun a sa propre racine du projet, en évitant le double de la compilation:

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

Répertoire complet de mise en page:

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

Le stub-comme point d'entrée le fichier mylib-commandline/Main.hs ressemble à ceci:

module Main where

import qualified Web.Mylib.Server.Main as MylibServer

main :: IO ()
main = MylibServer.main

Vous avez besoin d'eux, car un executable doit commencer sur un module appelé simplement Main.

Votre mylib.cabal ressemble à ceci:

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 permettra de construire la bibliothèque et les deux fichiers exécutables sans double compilation de la bibliothèque, parce que chacun est dans leur propre hs-source-dirs et les exécutables dépendent de la bibliothèque.

Vous pouvez toujours exécuter les fichiers exécutables avec runghc de votre projet de racine, à l'aide de l' -i commutateur de dire où il doit regarder pour les modules (à l'aide d' : comme séparateur):

runhaskell -isrc:mylib-commandline mylib-commandline/Main.hs

runhaskell -isrc:mylib-server mylib-server/Server.hs

De cette façon, vous pouvez avoir une mise en page propre, des exécutables avec helper modules, et tout fonctionne toujours avec runhaskell/runghc et ghci. Pour éviter de taper ce drapeau à plusieurs reprises, vous pouvez ajouter quelque chose de similaire à

:set -isrc:mylib-commandline:mylib-server

pour votre .ghci le fichier.


Notez que, parfois, doit séparer votre code dans des colis séparés, par exemple, mylib, mylib-commandline et mylib-server.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X