Skip to content

stack VS cabal install и при чём тут вообще cabal

Aleksey Pirogov edited this page Jun 7, 2018 · 1 revision

stack VS cabal install и при чём тут вообще cabal?

Терминология

Cabal

Cabal - библиотека, использующаяся и в stack, и в cabal-install.

cabal-install

cabal-install - "команда cabal", т.е. программа, предоставляющая CLI для работы с библиотекой cabal и репозиторием пакетов hackage.

stack

stack - программа, отвечающая за весь цикл разработки на Haskell. Использует библиотеку cabal. Никак не использует (не вызывает "под капотом") cabal-install.

Различия между stack и cabal-install

Установка пакетов

cabal-install позволяет устанавливать пакеты в глобальное окружение. Более того, по умолчанию туда пакеты и устанавливаются, что может привести к печально известному "cabal hell" - ситуации, когда пакеты, установленные для нужд одного проекта, начинают мешать разработке другого. Для решения этой проблемы в cabal-install добавлены песочницы (sandboxes) - если проект находится в песочнице, то cabal-install устанавливает пакеты в эту песочницу, а глобальное окружение остаётся нетронутым (и наоборот, установленные глобально пакеты не влияют на песочницу). Минус этого подхода заключается в том, что каждая песочница полностью изолирована, а значит все пакеты-зависимости приходится компилировать для каждой песочницы отдельно.

stack не устанавливает пакеты явно - пакеты-зависимости устанавливаются при сборке проекта автоматически (да, stack имеет команду install, но это не команда для установки пакетов-зависимостей!). А ещё stack принципиально для каждого проекта создаёт отдельное окружение, что исключает упомянутый выше "cabal hell". При этом пакеты, использованные в каком либо из проектов ранее, для нового проекта пересборки не потребуют (если версия зависимости указана та же, или указан тот же resolver).

TODO: cabal-install + new-commands

Версионирование зависимостей

cabal-way

Библиотека cabal подразумевает, что версии зависимостей либо указываются в .cabal-файле явно, либо опускаются совсем.

Если конкретная версия пакета не указана (указан диапазон, либо версия вообще опущена), то cabal будет пытаться использовать самую свежую версию, доступную на hackage. Этот подход неидеален, т.к. в один момент проект скомпилируется, а позже в другом окружении версии пакетов настолько разойдутся, что проект перестанет собираться.

Можно запомнить текущие версии пакетов с которыми проект собирается и либо прописать версии явно в .cabal-файле, либо воспользоваться командой cabal freeze.

Первый вариант подходит для библиотек: библиотеки не используются сами по себе, но становятся частью других проектов. Которые могут быть собраны разными способами. И чтобы библиотека не слишком стесняла пользователя, версии зависимостей в её .cabal-файле стоит указывать в виде некоего допустимого диапазона (который можно выяснить, попробовав собрать библиотеку с разными версиями зависимостей).

Вариант с cabal freeze подходит для конечных приложений. При "заморозке" версии всех установленных пакетов (и зависимостей и зависимостей зависимостей) явно сохранятся в дополнительном файле cabal.config и если в дальнейшем захочется обновить пакеты, то можно будет удалить этот файл, установить новые версии пакетов и повторно сделать "заморозку".

stack-way

stack использует концепцию snapshots - силами stackage делаются "срезы" hackage, влючающие в себя некое множество пакетов конкретных версий, совместимых (компилирующихся) друг с другом при помощи определённой версии компилятора. Т.о. некий snapshot а) специфицирует версию компилятора и б) фиксирует версии отдельных пакетов. Что позволяет

  • в большинстве случаев не волноваться о совместимости пакетов между собой,
  • обновлять все зависимости разом (переходом на другой snapshot),
  • воспроизводить окружение "на новом месте".

В каждом stack-driven проекте в stack.yaml присутствует параметр resolver, содержащий имя снапшота, с которым проект должен собираться.

TODO: дать ссылку на руководство по stack (а сначала написать оное).