想象一下如下的Makefile:
stage1 : Stage1.hs
ghc -o stage1 Stage1.hs
Stage1.hs : stage0
stage0 > Stage1.hs
stage0 : Stage0.hs
ghc -o stage0 Stage0.hs
Run Code Online (Sandbox Code Playgroud)
当前目录首先包含Makefile和Stage0.hs,并生成stage1.
以下是问题:
对于像这样的情况,Cabal很棘手.
正如你所说,如果你能把所有东西都挤进去Setup.hs,你就会把头疼的次数降到最低.
如果您有非常复杂的预处理器,我建议这样做:
为每个预处理器创建一个cabal包,具有自己的依赖项等.因此,对于stage0,您将拥有如下的cabal文件:
Name:
mypackage-stage0
Version:
0.1
-- ...
Executable mpk-stage0
Default-language:
Haskell2010
Main-is:
Stage0.hs
-- ...
Run Code Online (Sandbox Code Playgroud)因为stage1,您需要生成源代码,因此preBuild在您的Setup.hsfor mypackage-stage1中添加一个运行mpk-stage0可执行文件的钩子:
main =
defaultMainWithHooks simpleUserHooks
{ preBuild =
-- ... something involving `system "mpk-stage1 Stage1.hs"`
-- Note that shell redirection `> bla.hs` doesn't necessarily work
-- on all platforms, so make your `mpk-stage1` executable take an
-- output file argument
}
Run Code Online (Sandbox Code Playgroud)
然后,您将在上一阶段添加构建工具依赖项:
Executable mpk-stage1
-- ...
Main-is:
Stage1.hs
Build-tools:
mypackage-stage0
Run Code Online (Sandbox Code Playgroud)
这应该适用于最近的cabal版本; 否则,您可能必须添加Build-depends:依赖项.
每次进行级联更改时,您都需要依次重建每个包(这是必要的,因为cabal不管理跨项目依赖项更改),因此您需要一个for project in mypackage-stage0 mypackage-stage1; do (cd $project; cabal install); done类似的脚本.
Cabal从来就不是为这种项目而建的,所以如果你想做这样的事情会很棘手.如果您想以更连贯的方式生成代码,则应该考虑使用Template Haskell.