Как уменьшить дублирование в полях, зависящих от сборки файла .cabal?
Вот файл .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"?
Изменить: информацию о версии.
- cabal-dev 0.9
- cabal-install 0.10.2
- Библиотека Cabal 1.10.2.0
- GHC 7.0.4
- Платформа Haskell 2011.4.0.0
Ответы
Ответ 1
Можно ли каким-либо образом заменить длинный список пакетов, зависящих от сборки, для набора тестов с "такими же, как и для исполняемого файла, а также QuickCheck"?
Не то, чтобы я знал. Тем не менее, существует способ упоминать только один список пакетов, зависящих от сборки, путем структурирования вашего проекта в три цели:
- библиотека, которая содержит весь ваш код и нуждается в длинном списке, зависящем от сборки.
- исполняемый файл, который состоит только из одного файла и зависит от базы и библиотеки сверху.
- тестовый пакет, который зависит от библиотеки сверху и пакетов тестирования, которые вы используете.
Возможно, такой подход - это то, что предлагает indygemma, но предложенный там файл кабалы не достигнет этого, как замечает Норман Рэмси в комментарии. Здесь основные моменты того, что вам нужно в файле кэба. Для полного примера, который работает для меня, вы можете посмотреть этот файл 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 и, что еще важнее, меньше дублирования в процессе сборки: библиотечный код будет создан только один раз, а затем будет связан как с исполняемым, так и с тестовым набором.
Ответ 2
Вы также можете использовать hpack вместо записи файла .cabal вручную:
В формате hpack package.yaml вы можете указать общее поле dependencies
, чьи записи добавляются в поле всех компонентов build-depends
при создании файла .cabal.
Например, см. hpack package.yaml и сгенерированный hpack.cabal.
Чтобы начать использовать hpack с существующим пакетом, вы можете использовать hpack-convert, который будет генерировать package.yaml из существующего файла .cabal.
Чтобы создать новый пакет, использующий hpack, вы можете использовать шаблон stack simple-hpack
следующим образом: stack new mypkg simple-hpack
.
Если вы используете stack для разработки, вам не нужно вручную вызывать hpack
для восстановления файла .cabal с обновленный пакет package.yaml - stack сделает это автоматически.
Ответ 3
Нет простого способа:
-
вы можете использовать m4 и указывать свои зависимости один раз, но тогда вам нужно будет перерабатывать ваш файл Cabal через m4 всякий раз вы меняете его.
-
вы можете переместить код, который вы тестируете, в библиотеку, а затем указать библиотеку в вашем Build-depends для теста. Это требует, чтобы вы установили библиотеку даже для запуска теста.
-
Вы просто не можете поместить тест в файл cabal. Постройте его с помощью ghc -make, который будет тянуть зависимости. Но тогда вы теряете интеграцию с кабкой.
Ответ 4
Для файлов .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.*