Skip to content

Установка вспомогательных программ для разработки на Haskell с помощью stack

Yuriy Syrovetskiy edited this page May 28, 2018 · 4 revisions

Установка

Большая часть расширений для редакторов, обеспечивающих поддержку Haskell предполагает наличие в окружении некоторых программ. Это всевозможные hie, hlint, stylish-haskell, hindent, weeder и т.п. Некоторая сложность заключается в том, что работоспособность таких программ часто зависит от той версии компилятора, с которой оные собраны.

stack имеет специальный флаг для команды build: stack build --copy-compiler-tool (в противовес команде stack build --copy-bins, а именно эта команда скрывается за алиасом stack install!). При сборке программы с этим флагом, оная будет скопирована в директорию вида ~/.stack/programs/x86_64-linux/ghc-8.2.2/bin/ghc.

Этот способ установки хорош тем, что программы становятся доступны для использования во всех stack-based проектах, сходных версией компилятора (версии снапшотов могут быть разными!). Повторная установка потребуется только при переходе на другую версию компилятора (если используется несколько версий компилятора, то нужно будет установить инструментарий для каждой).

Использование

Программы, установленные "поближе к компилятору", доступны в окружении, которое создаёт stack при выполнении команд через stack exec -- .... А значит

  • какой-нибудь hlint будет доступен через stack exec -- hlint ...
  • редактор, запущенный через stack exec -- sublime будет "видеть" все установленные указанным выше способом программы.

Что можно улучшить

Вместо того, чтобы делать stack exec для каждого вызова hlint, можно расширить текущее окружение:

$ export PATH=$(stack path --compiler-tools-bin):$PATH

Теперь в текущем сеансе оболочки все инструменты будут видны непосредственно.

Автор пользуется следующей специально написанной bash-функцией

gostack() {
    env PATH=$(stack path --compiler-tools-bin):$PATH debian_chroot=stacked bash
}

Вызов этой функции порождает новую копию оболочки с расширенным окружением, которая прямо в приглашении будет показывать, что работает в контексте (если формат приглашения отображает переменную $DEBIAN_CHROOT что обычно для debian-based дистрибутивов Linux, например) - примерно так:

(stacked)user@host:/home/user $

Использование свежих версий программ

Stack устанавливает программы, руководствуясь версиями пакетов, указанными в снапшоте текущего проекта. Если же stack запускается вне проекта, то подразумевается некий "глобальный проект", stack.yaml которого можно найти по пути ~/.stack/global-project/stack.yaml (этот проект создаётся при первом запуске stack и используется, скажем, при выполнении stack ghci вне конкретного проекта).

Чтобы иметь программы свежими, но при этом собранными нужной версией компилятора и с использованием пакетов, которые используются в рабочих проектах, можно воспользоваться подходом автора: создать проект-пустышку со stack.yaml следующего вида (версии указаны для примера):

resolver: lts-11.0
packages:
  - .
extra-deps:
  - ghcid-0.7
  - hlint-2.1.3
  - hoogle-5.0.17.3
  - weeder-1.0.3
  - hindent-5.2.5
  - stylish-haskell-0.9.0.2
  - hasktags-0.69.5
# deps of deps
  - haskell-src-exts-1.20.2
  - http-conduit-2.3.1
  - extra-1.6.6

Остальное содержимое проекта важности не имеет, нужно лишь, чтобы проект успешно собирался. Далее нужно каким-то образом сказать stack, чтобы он собрал перечисленные пакеты и скопировал исполняемые файлы в нужное место. Автор делает это с помощью следующего Makefile:

.PHONY: install
install:
	stack build --copy-compiler-tool hlint hoogle weeder stylish-haskell hindent hasktags ghcid

Т.о. использование проекта сводится к вызову make - пакеты соберутся, бинарные файлы скопируются. В дальнейшем потребуется актуализация версий пакетов и/или версии снапшота и повторный запуск make. Если таковая необходимость есть, можно завести несколько файлов stack.yaml с разными версиями снапшотов и указывать оные через соответствующую опцию в командах Makefile.

Исходники мета-проекта автора можно посмотреть тут.