首页 文章

如何减少.cabal文件的build-depends字段中的重复?

提问于
浏览
57

这是一个.cabal文件:

Name:                myprogram
Version:             0.1
-- blah blah blah
Cabal-version:       >=1.9.2

Executable myprogram
  HS-source-dirs:       src
  Main-is:              Main.hs
  Build-depends:        attoparsec == 0.10.*,
                        base == 4.3.*,
                        -- long long list of packages

Test-Suite test
  HS-source-dirs:       test, src
  Type:                 exitcode-stdio-1.0
  Main-is:              Main.hs
  Build-depends:        attoparsec == 0.10.*,
                        base == 4.3.*,
                        -- long long list of packages
                        QuickCheck == 2.4.*

有没有什么办法可以用“与可执行文件相同,加上QuickCheck”替换测试套件的长编译依赖包列表?

Edit: 版本信息 .

  • cabal-dev 0.9

  • cabal-install 0.10.2

  • Cabal library 1.10.2.0

  • GHC 7.0.4

  • Haskell平台2011.4.0.0

5 回答

  • 3

    从版本2.2开始,Cabal支持常见的节,重复数据删除构建信息字段:https://cabal.readthedocs.io/en/latest/developing-packages.html#common-stanzas

    cabal-version:       2.2
    name:                myprogram
    version:             0.1
    -- blah blah blah
    
    common deps
      build-depends: base ^>= 4.11,
                     -- long long list of packages
      ghc-options: -Wall
    
    library
      import: deps
      exposed-modules: Foo
    
    test-suite tests
      import: deps
      type: exitcode-stdio-1.0
      main-is: Tests.hs
      build-depends: foo
    
  • -1

    有没有什么办法可以用“与可执行文件相同的版本,加上QuickCheck”替换测试套件的长版依赖版程序包?

    从来没听说过 . 但是,通过将项目结构化为三个目标,有一种方法只能提及 build-depends 包的列表:

    • 包含所有代码的库,需要长构建依赖列表 .

    • 一个只包含一个文件的可执行文件,它依赖于base和上面的库 .

    • 依赖于上面的库以及您正在使用的测试包的测试套件 .

    也许这种方法就是你在Cabal文件中需要的主要内容 . -1818688_ . 有关适用于我的完整示例,您可以查看this Cabal file .

    name: my-program
    version: ...
    
    library
      hs-source-dirs: src-lib
      build-depends: base, containers, ...
      exposed-modules: My.Program.Main, ...
    
    executable my-program
      hs-source-dirs: src-exec
      main-is: my-program.hs
      Build-depends: base, my-program
    
    test-suite tests
      type: exitcode-stdio-1.0
      hs-source-dirs: src-test
      main-is: tests.hs
      other-modules: ...
      build-depends: base, my-program, test-framework, ...
    

    重点:

    • 这三个目标有三个独立的源目录 . 这有必要阻止GHC在构建其他目标时重新编译库文件 .

    • 所有应用程序代码都在库中 . 可执行文件只是一个包装器,如下所示:

    import My.Program.Main (realMain)
    main = realMain
    
    • 该库公开了测试所需的所有模块 .

    最后一点强调了这种方法的缺点:您最终不得不暴露内部模块 . 这种方法的主要好处是Cabal文件中的重复较少,更重要的是,构建过程中的重复较少:库代码只构建一次,然后链接到可执行文件和测试套件中 .

  • -5

    您也可以考虑使用hpack而不是手动编写.cabal文件:

    在hpack的package.yaml格式中,您可以指定一个公共 dependencies 字段,在生成.cabal文件时,其条目将添加到每个组件的 build-depends 字段中 .

    例如,请参阅hpack自己的package.yaml和生成的hpack.cabal .

    要开始在现有包中使用hpack,可以使用hpack-convert,它将从现有的.cabal文件生成package.yaml .

    要创建一个使用hpack的新包,可以使用stack的 simple-hpack 模板,如下所示: stack new mypkg simple-hpack .

    如果使用stack进行开发,则不必手动调用 hpack 从更新的package.yaml重新生成.cabal文件 - 堆栈将自动执行此操作 .

  • 7

    没有简单的方法:

    • 您可以使用m4并指定一次依赖项,但是每当您更改它时,您将需要通过m4重新处理您的Cabal文件 .

    • 您可以将要测试的代码移动到库中,然后在Build-depends中指定库以进行测试 . 这要求您安装库甚至只是为了运行测试 .

    • 您根本不能将测试放在cabal文件中 . 使用ghc --make构建它,它将引入依赖关系 . 但是你失去了集成 .

  • 32

    .cabal文件有一个可选的 library 部分,可以解决您的问题 .

    name:              myprogram
    version:           0.1
    -- blah blah blah
    cabal-version:     >=1.9.2
    
    library
        build-depends: attoparsec == 0.10.*
                     , base == 4.3.*
                     -- long long list of packages
    
    executable myprogram
        hs-source-dirs: src
        main-is:        Main.hs
    
    test-suite test
        hs-source-dirs: test, src
        type:           exitcode-stdio-1.0
        main-is:        Main.hs
        build-depends:  QuickCheck == 2.4.*
    

相关问题