Stackで不用意に依存関係を触って失敗したので、extra-deps
を設定する方法についてちゃんと調べてみました。stack solver
とstack init --solver
の振舞いの相違について例を用いて説明します。
Stackのバージョンは0.1.10.0 i386です。執筆時点でのlts
の最新バージョンは6.11です。
またstack
コマンドには適宜--force
を付けていると読み替えてください。
入力例
元はstack new solver-test new-template
で生成したものです。それを、Stackageに含まれないuri
パッケージと依存関係に起因するエラーの原因となるgtk
パッケージを使うように編集したわざとらしい例になっています。
name: solver-test
version: 0.1.0.0
synopsis: Initial project template from stack
description: Please see README.md
homepage: https://github.com/githubuser/solver-test#readme
license: BSD3
license-file: LICENSE
author: Author name here
maintainer: example@example.com
copyright: 2016 Author name here
category: Web
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10
library
hs-source-dirs: src
exposed-modules: Lib
build-depends: base >= 4.7 && < 5
default-language: Haskell2010
executable solver-test-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, solver-test
, gtk
, uri
default-language: Haskell2010
test-suite solver-test-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, solver-test
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010
source-repository head
type: git
location: https://github.com/githubuser/solver-test
module Main where
import Lib
import Graphics.UI.Gtk
import Text.URI
main :: IO ()
main = return ()
とりあえずstack init
stack init
すると次のようなメッセージが出力されます。
Writing default config file to: /home/.../dev/haskell/solver-test/stack.yaml
Basing on cabal files:
- /home/.../dev/haskell/solver-test/solver-test.cabal
Checking against build plan lts-6.10
* Build plan did not match your requirements:
uri not found
- solver-test requires -any
Checking against build plan lts-5.15
* Build plan did not match your requirements:
uri not found
- solver-test requires -any
Checking against build plan nightly-2016-08-06
* Build plan did not match your requirements:
uri not found
- solver-test requires -any
Checking against build plan nightly-2016-05-25
* Build plan did not match your requirements:
uri not found
- solver-test requires -any
Checking against build plan lts-6.11
* Build plan did not match your requirements:
uri not found
- solver-test requires -any
Checking against build plan lts-5.18
* Build plan did not match your requirements:
uri not found
- solver-test requires -any
There was no snapshot found that matched the package bounds in your .cabal files.
Please choose one of the following commands to get started.
stack init --resolver lts-6.10
stack init --resolver lts-5.15
stack init --resolver nightly-2016-08-06
stack init --resolver nightly-2016-05-25
stack init --resolver lts-6.11
stack init --resolver lts-5.18
You'll then need to add some extra-deps. See:
https://github.com/commercialhaskell/stack/blob/release/doc/yaml_configuration.md#extra-deps
You can also try falling back to a dependency solver with:
stack init --solver
長ったらしいですが、「uri
パッケージが見つからない」ということをスナップショットのバージョンごとに言っているだけです。
さらに後半部分では次に試すべきことが2つ書かれています。
-
stack init --resolver xxx
の後、extra-deps
を編集。 -
stack init --solver
。
まずは1.の方法から見てみます。
1.の方法 - stack solver
今回はresolverとしてlts-6.10
を選びます。
$ stack init --resolver lts-6.10 --force
Writing default config file to: /home/.../dev/haskell/solver-test/stack.yaml
Basing on cabal files:
- /home/.../dev/haskell/solver-test/solver-test.cabal
Checking against build plan lts-6.10
* Build plan did not match your requirements:
uri not found
- solver-test requires -any
Selected resolver: lts-6.10
Wrote project config to: /home/.../dev/haskell/solver-test/stack.yaml
無事stack.yamlが生成されたので、次はextra-deps
への記述を行います。記述内容はstack solver
で計算させることが出来ます。時間とメモリを食う作業なので注意。
$ stack solver
Asking cabal to calculate a build plan, please wait
This command is not guaranteed to give you a perfect build plan
It's possible that even with the changes generated below, you will still need to do some manual tweaking
extra-deps:
- uri-0.1.6.4
To automatically modify your stack.yaml file, rerun with '--modify-stack-yaml'
今回extra-deps
に記述するべき内容が出力されるので、これをstack.yamlにコピペしてやればOKです。
また、メッセージの最後にある通り、--modify-stack-yaml
を付けてやればstack.yamlを自動で編集してくれます。但し、結果を覚えてくれる訳ではないので同じだけ時間がかかります。
2.の方法 - stack init --solver
次に2.の方法を試してみます。
stack init --solver
を実行するとstack.yamlが次のような内容になります。
# Specifies the GHC version and set of packages available (e.g., lts-3.5, nightly-2015-09-21, ghc-7.10.2)
resolver: ghc-7.10.3
# Local packages, usually specified by relative directory name
packages:
- '.'
# Packages to be pulled from upstream that are not in the resolver (e.g., acme-missiles-0.3)
extra-deps:
- cairo-0.13.3.0
- gio-0.13.3.0
- glib-0.13.4.0
- gtk-0.14.5
- pango-0.13.3.0
- safe-0.3.9
- uri-0.1.6.4
- utf8-string-1.0.1.1
resolverがghc
になっていることに注意してください。この場合stackは、Stackageのスナップショットではなくコンパイラ付属のパッケージを使用します。実際extra-deps
に追加されたcairo
、gio
、glib
、gtk
、pango
、safe
、utf8-string
はStackage(例えばlts-6.10)に含まれているものです。
そしてこれはビルドに失敗し、次のようなエラーを出力します。
/tmp/stack20983/cairo-0.13.3.0/Setup.hs:5:8:
Could not find module ‘Gtk2HsSetup’
Use -v to see a list of the files searched for.
Gtk2HsSetup
はgtk2hs-buildtools
というパッケージ(これも本来Stackageに含まれる)のバージョン0.13.1.0以降が公開しているモジュールです。今回はこのモジュールに対する依存関係を解決できなかった1ということですね。
こちらに書いてありますが、stack init --solver
ではコンパイルできるものが出てくるとは限りません。
Stackageのスナップショットを使わないというのは非常にもったいないので、stack init --solver
を使うのはなるべく控えたほうが良さそうです。
まとめ
-
stack solver
の場合は出力をコピペしてやる必要がある。但し、--modify-stack-yaml
を付けてやれば自動編集してくれる。 -
stack init --solver
ではビルドできるものが出てくるとは限らない。 - stackのメッセージはとても親切なのでよく読むべき。