59

这是一个 .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”替换测试套件的构建依赖包的长列表?

编辑:版本信息。

  • 阴谋集团开发 0.9
  • 阴谋安装 0.10.2
  • 阴谋集团图书馆 1.10.2.0
  • GHC 7.0.4
  • Haskell 平台 2011.4.0.0
4

5 回答 5

33

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

从来没听说过。但是,有一种方法可以只提及build-depends一次包列表,方法是将您的项目构建为三个目标:

  1. 一个包含所有代码的库,并且需要很长的构建依赖列表。
  2. 一个只包含一个文件的可执行文件,并且依赖于基础和上面的库。
  3. 一个依赖于上述库的测试套件,以及您正在使用的测试包。

也许这种方法是 indygemma 的答案所建议的,但正如 Norman Ramsey 在评论中指出的那样,那里提出的阴谋集团文件不会完全实现它。这是您在 Cabal 文件中需要的要点。有关适用于我的完整示例,您可以查看此 Cabal 文件

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 文件中的重复更少,也许更重要的是,在构建过程中的重复更少:库代码将只构建一次,然后链接到可执行文件和测试套件.

于 2013-08-19T09:19:01.263 回答
10

由于 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
于 2018-09-20T16:53:03.870 回答
4

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

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

例如,查看 hpack 自己的package.yaml和生成的hpack.cabal

要开始将 hpack 与现有包一起使用,您可以使用hpack-convert从现有的 .cabal 文件生成 package.yaml。

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

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

于 2016-10-08T23:02:21.710 回答
-1

没有简单的方法:

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

  • 您可以将要测试的代码移出到库中,然后在 Build-depends 中为测试指定库。这需要您安装一个库,即使只是为了运行测试。

  • 您根本不能将测试放在 cabal 文件中。使用 ghc --make 构建它,它将引入依赖项。但是你失去了阴谋集团的整合。

于 2013-05-30T02:38:41.727 回答
-5

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

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.*
于 2012-04-15T16:58:52.887 回答