Stack: ビルドツール

Last Change:03-Jul-2016.
Author:qh73xe
Reference:http://docs.haskellstack.org/en/stable/README/

このページでは Haskell の開発用ビルドツール stack について 導入方法と簡単な使い方の紹介をします。

これは何??

現状では Haskell を使おうと思える方は 多分、他の言語でプログラミングを行ったことのある方なのだと思います。

もし python を使ったことのある方でしたら pyenv というツールをご存知の方も多いと思います。 ざっくり言えば、この Haskell 版だと思ってくれればよいです。

種々の開発を同じ PC で行っていると、 割と環境依存なコードを書くことになります。 例えばライブラリを利用している場合などでは、 別のPCを使うと、そもそもライブラリが入っていないとか、 ライブラリのバージョンが異なっており、以前動いたスクリプトが動かないぜということも多いかと。 或いはライブラリ同士の依存関係の問題で、うまく行かない場合もあります。 こういう問題を解決する方法の一つにプロジェクト亊に、使用する Haskell やそのライブラリを分けて管理するという方法があります。 こうしておけば、最低限そのプロジェクトで前提としている環境は全て記録されていますから、まぁなんとかなるだろうと。

Stack もこういう発想からできているツールで、 プロジェクトごとに使用する Haskell 環境を管理することができます。

導入方法

導入方法は公式のページに従うとよいです。

ここでは 2016-07-03 の段階での Linux(Fedora24) を使用している場合の方法を記述します。

$ curl -sSL https://s3.amazonaws.com/download.fpcomplete.com/fedora/24/fpco.repo | sudo tee /etc/yum.repos.d/fpco.repo
$ sudo dnf -y install stack

基本的な使い方

雛形の作成

テスト用のプロジェクトを作成してみます。 まずは適当なディレクトリを作成し、そこに stack 環境を作成します。 このサイトでは ~/Documents/testHaskell にプロジェクトを作成すると考えます。

$ mkdir ~/Documents/testHaskell
$ cd ~/Documents/testHaskell
$ stack new

~/Documents/testHaskell にプロジェクトの雛形が作成されました。 続いてはとりあえず雛形の段階でビルドをしてみましょう。

$ stack setup
$ stack build

stack setup で環境構築を行います。 これは初回に必要です。 一方、 stack build が色々書いたスクリプトをビルドします。

最後にビルドされた生成物を実行するには以下のコマンドを使用します。

$ stack exec testHaskell-exe
someFunc

Stack の構成

さて、雛形の編集を考えます。 まず実際の実行用スクリプトは app/Main.hs になります。

これは以下のようになっています。

app/Main.hs
1
2
3
4
5
6
module Main where

import Lib

main :: IO ()
main = someFunc

これをみると, Lib というライブラリを読み込み このライブラリの someFunc という関数を実行していることがわかります。 つまり、 app/Main.hs はあくまでも実行用のコードが書かれているだけで、 関数自身は別のファイルで管理するようにしていることがわかります。

今回の場合、 src/Lib.hs というものが実際の関数が書かれているファイルになります。 これは以下のようになっています。

src/Lib.hs
1
2
3
4
5
6
module Lib
    ( someFunc
    ) where

someFunc :: IO ()
someFunc = putStrLn "someFunc"

Stack で Haskell プロジェクトを作成していく場合、 基本的にはこの src/Lib.hs を編集していくことで実際のロジックを記述することになると思います。

これを編集したらば再び stack build をすることで プロジェクトのビルドができます。

stack の設定

他のパッケージを使用する

プロジェクト内で何らかのパッケージを利用したい場合、 <プロジェクト名>.cabal というファイル(以下 .cabal)を編集します。

具体的には以下に強調している部分にライブラリ名を記述します。 各ライブラリはカンマで区切ります。

.cabal
1
2
3
4
5
6
...
library
  hs-source-dirs:      src
  exposed-modules:     Lib
  build-depends:       base >= 4.7 && < 5, <利用したいライブラリ名>
  default-language:    Haskell2010

その上で stack build を行うとライブラリを導入した上で、 ビルドを行ってくれます。

  • 因みに library の項目で設定している場合 src 以下のスクリプトでライブラリを読み込む必要があります。
  • 一方で、app 以下のスクリプトでライブラリを読み込みたい場合、 executable の項目にある build-depends を設定する必要があります。

実行ファイル名を変更する

stack build でビルドされる際の名前は .cabal ファイルで管理されています。 具体的には以下に強調している部分に実行ファイル名を記述します。

.cabal
1
2
3
4
5
6
7
...
executable <実行ファイル名>
  hs-source-dirs:      app
  main-is:             Main.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base, soundtest-haskell
  default-language:    Haskell2010

複数の実行ファイルを用意する

場合によってはあるプロジェクトでビルドしたいファイルが一つではない場合もあると思います。 このような場合、 .cabal の executable の項目を増やします。

.cabal
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
...
executable test1
  hs-source-dirs:      app
  main-is:             test1.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base, soundtest-haskell
  default-language:    Haskell2010
...
executable test2
  hs-source-dirs:      app
  main-is:             test2.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base, soundtest-haskell
  default-language:    Haskell2010

この時 test1.hs, test2.hs は app 以下のディレクトリにある必要があります。

  • hs-source-dirs の設定で変更可能ですが

モジュールのテストを行いたい

stack を使用して開発を進める場合、基本的なロジックは src/Lib.hs に記述することが多いと思います。 ここで書かれたロジックのテストを対話的に行う場合、 stack ghci とするとよいかと思います。 このようにすることで src/Lib.hs が読み込まれた状態で対話環境が起動します。