Как уменьшить дублирование в полях build-depends файла. cabal?


здесь .cabal file:

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-установить 0.10.2
  • Cabal library 1.10.2.0
  • GHC 7.0.4
  • Платформа Haskell 2011.4.0.0
5 56

5 ответов:

начиная с версии 2.2 Cabal поддерживает общие строфы, чтобы дедуп build info поля: 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

есть ли способ заменить длинный список зависящих от сборки пакетов для набора тестов на "то же, что и для исполняемого файла, плюс QuickCheck"?

насколько мне известно, нет. Однако, есть способ только упомянуть список build-depends пакеты один раз, структурируя свой проект на три цели:

  1. библиотека, которая содержит весь ваш код и нуждается в длинном списке build-depends.
  2. исполняемый файл, который состоит только из одного файл, и зависит от базы и библиотеки сверху.
  3. набор тестов, который зависит от библиотеки сверху, и пакеты тестирования, которые вы используете.

возможно, этот подход-это то, что предлагает ответ indygemma, но предложенный там файл 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 и, возможно, что более важно, меньше дублирования в процессе сборки: код библиотеки будет построен только один раз, а затем связан как с исполняемым файлом, так и с набором тестов.

вы также можете рассмотреть возможность использования hpack вместо того, чтобы писать .cabal файл от руки:

в пакете hpack.формат yaml, вы можете указать общий dependencies поле, записи которого добавляются к каждому компоненту'build-depends поле при создании .файл междусобойчик.

например, см. hpack по пакета.и YAML и созданный hpack.Кабал.

чтобы начать использовать hpack с существующим пакетом, вы можете использовать hpack-преобразования который будет генерировать пакет.ямл из существующего .файл междусобойчик.

создать новый пакет, который использует hpack, вы можете использовать стек simple-hpack шаблон вот так: stack new mypkg simple-hpack.

если вы используете стек для развития вам не нужно звонить hpack вручную, чтобы восстановить .файл cabal из обновленного пакета.yaml-stack сделает это автоматически.

нет простой способ:

  • можно использовать m4 и укажите свои зависимости один раз, но тогда вам нужно будет повторно обработать ваш файл Cabal через m4 всякий раз, когда вы его меняете.

  • вы можете переместить тестируемый код в библиотеку, а затем указать библиотеку в своей сборке-зависит от теста. Это требует установки библиотеки даже просто для запуска теста.

  • вы можете просто не ставить тест в файл кабала вообще. Постройте его с помощью ghc --make, который будет тянуть в зависимости. Но тогда вы теряете кабальную интеграцию.

по желанию библиотека для .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.*