Как сделать проект Haskell cabal с библиотекой + исполняемыми файлами, которые все еще работают с runhaskell/ghci?
если вы объявить библиотеку + исполняемые разделы в файле cabal, избегая двойной компиляции библиотеки поместив библиотеку в hs-source-dirs каталог, вы обычно не можете запустить свой проект с ghci и runhaskell больше, особенно если исполняемые файлы имеют вспомогательные модули.
что такое рекомендуемый макет проекта, который
- только строит то, что нужно после
- позволяет использовать
runhaskell
- имеет чистую структуру без хаков?
2 ответов:
предположим, что у вас есть
mylibбиблиотека, иmylib-commandlineиmylib-serverисполняемые файлы.вы используете
hs-source-dirsдля библиотеки и каждого исполняемого файла, чтобы каждый имел свой собственный корень проекта, избегая двойной компиляции: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полный каталог макетов:
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 parserThe stub-like файл точки входа
mylib-commandline/Main.hsвыглядит так:module Main where import qualified Web.Mylib.Server.Main as MylibServer main :: IO () main = MylibServer.mainвы нуждаетесь в них, потому что
executableдолжен запускаться на модуле, который просто называетсяMain.код
mylib.cabalвыглядит так: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построит библиотеку и два исполняемых файла без двойной компиляции библиотеки, потому что каждый находится в своем собственномhs-source-dirsи исполняемые файлы зависят от библиотеки.вы все еще можете запускать исполняемые файлы с
runghcиз корня проекта, используя-iпереключитесь, чтобы сказать, где он должен искать модули (используя:в качестве разделителя):runhaskell -isrc:mylib-commandline mylib-commandline/Main.hs runhaskell -isrc:mylib-server mylib-server/Server.hsэтот таким образом, вы можете иметь чистый макет, исполняемые файлы с вспомогательными модулями, и все по-прежнему работает с
runhaskell/runghcиghci. Чтобы избежать повторного ввода этого флага, вы можете добавить что-то похожее на:set -isrc:mylib-commandline:mylib-serverна .
обратите внимание, что иногда следует разделить код на отдельные пакеты, например
mylib,mylib-commandlineиmylib-server.
можно использовать
cabal replчтобы запустить ghci с конфигурацией из файла cabal иcabal runдля компиляции и запуска исполняемых файлов. В отличие отrunhaskellиghci, используяcabal replиcabal runтакже правильно подбирает зависимости из песочниц cabal.
Comments