2012-09-06 47 views
53

如果將declare a library + executable sections in a cabal file while avoiding double compilation of the library放到hs-source-dirs目錄中,那麼通常不會再使用ghcirunhaskell運行項目,特別是如果可執行文件本身具有幫助程序模塊時。如何使用仍然運行runhaskell/ghci的庫+可執行文件來製作Haskell cabal項目?

什麼是推薦項目佈局

  • 只有建立所需要的一次
  • 允許使用runhaskell
  • 有一個乾淨的結構而不黑客?

回答

84

讓我們假設你有一個mylib庫,並mylib-commandlinemylib-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/runghcghci。爲避免重複鍵入此標誌,您可以添加類似於

:set -isrc:mylib-commandline:mylib-server 

到您的.ghci文件。


請注意,有時應將代碼拆分爲單獨的包,例如, mylibmylib-commandlinemylib-server

+0

完美答案,我在官方的Haskell頁面上尋找這樣簡單而直接的文章,但沒有運氣。可能我沒有花足夠的時間搜索,但這對我有很大的幫助。謝謝! – korCZis

3

您可以使用cabal repl來啓動ghci,使用cabal文件中的配置和cabal run來編譯和運行可執行文件。與runhaskellghci不同,使用cabal replcabal run也正確地從cabal沙箱中獲取依賴關係。

相關問題