问题描述
如果您在阴谋集团中声明一个库 + 可执行部分文件同时通过将库放入hs-source-dirs
目录来避免库的双重编译,您通常无法使用ghci
和 运行您的项目>runhaskell
,尤其是当可执行文件本身有帮助模块时.
If you declare a library + executable sections in a cabal file while avoiding double compilation of the library by putting the library into a hs-source-dirs
directory, you cannot usually run your project with ghci
and runhaskell
anymore, especially if the executables have helper modules themselves.
推荐的项目布局是什么
- 只构建一次需要的东西
- 允许使用
runhaskell
- 结构简洁,没有黑客攻击?
推荐答案
假设你有一个 mylib
库,以及 mylib-commandline
和 mylib-server
可执行文件.
Let's assume you have a mylib
library, and mylib-commandline
and mylib-server
executables.
您对库和每个可执行文件使用 hs-source-dirs
,这样每个可执行文件都有自己的项目根目录,避免双重编译:
You use hs-source-dirs
for the library and each executable so that each has their own project root, avoiding double 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
完整目录布局:
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
stub-like 入口点文件 mylib-commandline/Main.hs
看起来像这样:
The stub-like entry point file mylib-commandline/Main.hs
looks like this:
module Main where
import qualified Web.Mylib.Server.Main as MylibServer
main :: IO ()
main = MylibServer.main
您需要它们,因为 executable
必须从一个简单的名为 Main
的模块开始.
You need them because an executable
must start on a module simply called Main
.
你的 mylib.cabal
看起来像这样:
Your mylib.cabal
looks like this:
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
中,并且可执行文件依赖于图书馆.
cabal build
will build the library and the two executables without double compilation of the library, because each is in their own hs-source-dirs
and the executables depend on the library.
你仍然可以从你的项目根目录运行带有 runghc
的可执行文件,使用 -i
开关来告诉它应该在哪里寻找模块(使用 :
作为分隔符):
You can still run the executables with runghc
from your project root, using the -i
switch to tell where it shall look for modules (using :
as separator):
runhaskell -isrc:mylib-commandline mylib-commandline/Main.hs
runhaskell -isrc:mylib-server mylib-server/Server.hs
通过这种方式,您可以拥有干净的布局、带有辅助模块的可执行文件,并且所有内容仍然可以使用 runhaskell
/runghc
和 ghci
.为了避免重复输入这个标志,你可以添加类似
This way, you can have a clean layout, executables with helper modules, and everything still works with runhaskell
/runghc
and ghci
. To avoid typing this flag repeatedly, you can add something similar to
:set -isrc:mylib-commandline:mylib-server
到您的 .ghci
文件.
请注意,有时应该将您的代码拆分为单独的包,例如mylib
、mylib-commandline
和 mylib-server
.
Note that sometimes should split your code into separate packages, e.g. mylib
, mylib-commandline
and mylib-server
.
这篇关于如何使用仍然使用 runhaskell/ghci 运行的库+可执行文件制作 Haskell Cabal 项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!