问题描述
如果您,将库放入 hs-source-dirs
目录中,通常不能使用 ghci
和 runhaskell
,特别是如果可执行文件本身有辅助模块的话。
什么是推荐的项目布局
- 只会构建一次所需的内容
- 允许使用
runhaskell
- 有干净的结构,没有黑客? h2_lin>解决方案
如果您,将库放入 hs-source-dirs
目录中,通常不能使用 ghci
和 runhaskell
,特别是如果可执行文件本身有辅助模块的话。
什么是推荐的项目布局
runhaskell
假设您有一个 mylib
库,并且 mylib-commandline
和 mylib-server
可执行文件。
您可以使用 hs-source-dirs
用于库和每个可执行文件,以便每个文件都有自己的项目根目录,避免双重编译:
mylib /#项目根目录
mylib.cabal
src /#根目录该库
tests /
mylib-commandline /#命令行实用程序的辅助工具+辅助程序模块
mylib-server /#Web服务+辅助程序模块的根目录
$ b完整的目录布局:
mylib /#项目根目录
mylib.cabal
src /#库的根目录
Web /
Mylib.hs#主库模块
Mylib /
ModuleA#Mylib.ModuleA
ModuleB#Mylib.ModuleB
tests /
...
mylib-commandline /#命令行实用程序的根目录
Main.hs# 模块主要在哪里存根main = Web.Mylib.Commandline.Main.main
Web /
Mylib /
命令行/
Main.hs#CLI入口点
Arguments.hs#程序命令行参数解析器
mylib-server /#Web服务的根目录
Server.hs#module Main stub withmain = Web.Mylib.Server.Main.main
Web /
Mylib /
服务器/
Main.hs#服务器入口点
参数.hs#服务器命令行参数解析器
入口点文件
mylib-commandline / Main.hs
看起来像这样:
module主要在
中导入限定的Web.Mylib.Server.Main作为MylibServer
main :: IO()
main = MylibServer.main
您需要它们是因为
可执行文件
必须在一个简单的Main
。
您的
mylib.cabal
看起来像这样:
library
hs-source-dirs:src
exposed-modules:
Web.Mylib
Web.Mylib.ModuleA
Web.Mylib.ModuleB
build-depends:
base> = 4&& < = 5
,[库的其他依赖关系]
可执行mylib-commandline
hs-source-dirs:mylib-commandline
main-is:Main .hs
other-modules:
Web.Mylib.Commandline.Main
Web.Mylib.Commandline.Arguments
build-depends:
ase> = 4& amp ;&安培; < = 5
,mylib
,[CLI的其他依赖性]
可执行文件mylib-server
hs-source-dirs:mylib-server
main-is:Server.hs
other-modules:
Web.Mylib.Server.Main
build-depends:
base> = 4&& < = 5
,mylib
,warp> = XX
,[服务器的其他依赖关系]
$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
。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 withghci
andrunhaskell
anymore, especially if the executables have helper modules themselves.What is a recommended project layout that
runhaskell
Let's assume you have a mylib
library, and mylib-commandline
and mylib-server
executables.
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
Full directory layout:
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
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
You need them because an executable
must start on a module simply called Main
.
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
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.
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
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
to your .ghci
file.
Note that sometimes should split your code into separate packages, e.g. mylib
, mylib-commandline
and mylib-server
.
这篇关于如何用库+可执行文件构建一个Haskell cabal项目,该项目仍然可以通过runhaskell / ghci运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!