stack — это утилита для сборки проекта на языке haskell.
Чтобы разобраться с haskell, я решил переписать свой транслитератор клавиатурного ввода erswitcher на этом языке.
Вначале всё шло отлично. Я установил stask и компиллятор ghc:
# pacman -S stack ghc
И указал stack-y использовать системный ghc:
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.0.2
$ stack setup --system-ghc --resolver ltc-9.0.2
Создал проект:
$ stack new erswitcher
$ mv erswitcher erswitcher-2
Получился вот такой проект:
Пробежавшись по файлам я выяснил, что package.yaml используется для указания опций компилятора для сборки исполняемых файлов и юнит-тестов. Так же там прописан автор, лицензия и прочая информация для создания и публикации проекта на hackage.haskell.org. При каждом запуске stack на его основе генерирует файл <проект>.cabal.
Ошибка "Не найден модуль Prelude"
Однако при компилляции выскочила ошибка:
Я ожидал увидеть import Distribution.Simple
в app/Main.hs или src/Lib.hs, но поиск по проекту указал на Setup.hs. Я удалил содержимое Setup.hs и... осталась та же ошибка. При этом пакет distributive с библиотекой Distribution.Simple
был установлен:
$ ghc-pkg list | grep dist
distributive-0.6.2.1
$ stack install distribution
так же ругнулся, что версии зависимостей у distribution не подходят.
Оказалось, что нужно просто установить ghc-static, так как собирать бинарники с динамической линковкой stack не позволяет, даже если прописать опцию -dynamic в package.yaml:
# pacman -S ghc-static
Модуль Main в app/Main.hs нельзя переименовать
Дальше я перетиеновал модуль app/Main.hs на app/Erswitcher.hs. Соответственно и в файле изменил название модуля:
module Erswitcher where
import Lib
main :: IO ()
main = someFunc
В package.yaml заменил название модуля соответственно:
executables:
erswitcher-exe:
main: Erswitcher.hs
source-dirs: app
ghc-options:
- -dynamic
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- erswitcher
Это привело к ошибке:
<no location info>: error:
output was redirected with -o, but no output will be generated
because there is no Main module.
Оказывается, исходный файл бинарника может называться как угодно, а пакет в нём нужно называть всегда Main:
module Main where
import Lib
main :: IO ()
main = someFunc
Теперь всё скомпиллировалось и можно переходить к планированию архитектуры и тестам.
includedlibrary
В чём смысл статьи? Официальная документация раскрывает вопросы конфигурации и использования stack куда лучше. В статье же я смог найти только установку stack на arch, которая тоже крайне хорошо расписана на archwiki.
Таки позволяет
Есть ещё самый простой способ установки на арч - использовать официальный бинарник отсюда и позволить ему самому установить нужную версию ghc для вашего проекта. На этот случай есть скрипт, который сам качает stack и делает пакет для арча.