如果您在 cabal 文件中声明一个库 + 可执行部分,同时通过将库放入一个hs-source-dirs
目录来避免库的双重编译,您通常不能再使用ghci
and运行您的项目runhaskell
,特别是如果可执行文件本身具有帮助模块。
什么是推荐的项目布局
- 只构建一次需要的东西
- 允许使用
runhaskell
- 有没有黑客的干净结构?
如果您在 cabal 文件中声明一个库 + 可执行部分,同时通过将库放入一个hs-source-dirs
目录来避免库的双重编译,您通常不能再使用ghci
and运行您的项目runhaskell
,特别是如果可执行文件本身具有帮助模块。
什么是推荐的项目布局
runhaskell
假设您有一个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 parser
类似存根的入口点文件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
到你的.ghci
文件。
请注意,有时应该将您的代码拆分为单独的包,mylib
例如mylib-commandline
和mylib-server
.
您可以使用cabal repl
cabal 文件中的配置启动 ghci,并cabal run
编译和运行可执行文件。与runhaskell
and不同ghci
,使用cabal repl
andcabal run
还可以正确地从 cabal 沙箱中获取依赖项。