今陥っている状態とは関係ないと思うが、Haskell on Snow Leopard ← Passing Curiosityを読んでいなかった。読んでみたところ、どうやら Snow Leopard で Haskell の開発を行うためにやらなきゃいけないことがもう少しあるようなのでやることにした。
以下、上記URLに掲載されているエントリを訳してみた。誰かしらに役に立つかもしれない。
僕は Apple のファンボーイだってことを内緒にしてるんだけど、そんな僕は Snow Leopard を予約していて、手持ちの MacBook を発売日当日にアップグレードしたんだ。不幸にも、その作業は僕の Haskell 開発環境を完膚なきまでにぶち壊してくれた。僕はなんとかぶち当たった問題すべてを解決して、ここに解決方法を書き留めた。注意点はこの記事の最後に書いてあるから読んでみて欲しい。
最初に、GHC はなにもコンパイルしてくれなくなる。この問題はつまるところ、Snow Leopard とその中にあるコンパイラ全てが、64bit での処理がデフォになったってことだ。悲劇的なことに、GHC が Mac OS X 用に生成するコードは 32bit 用で、そのせいでアセンブラとリンカが以下のようなエラーを出すことになる。
/var/folders/1J/1JKije6yHpm78qqdjF5N2U+++TI/-Tmp-/ghc7743_0/ ghc7743_0.s:1357:0: suffix or operands invalid for `push' /var/folders/1J/1JKije6yHpm78qqdjF5N2U+++TI/-Tmp-/ghc7743_0/ ghc7743_0.s:1401:0: suffix or operands invalid for `push'</code>
解決方法は、GHC に対して -m32 フラグをコンパイラ(もし使われるなら), アセンブラ, そしてリンカへ渡すように設定することだ。
コレを実現するための最も手っ取り早い方法は、 /usr/bin/ghc (GHC の実体を呼び出すためのシェルスクリプト)を編集して、-optc-m32 opta-m32 -optl-m32 のフラグを付け足すことだ。これは、上記フラグがあらゆる場合に適用されることを明確にする。
悲しむべきことに、物語はまだ終わらない。Haskell での開発環境を整えるための次のステップは、cabal-install をインストールすることだ。こいつは HTTP と zlib の二つのパッケージに依存している。HTTP には特に問題はなく、./Setup.lhs を実行することでビルドも実行も可能だ。しかし、zlib は壊れてしまっているらしく、"互換性のないバージョンです" と実行時にレポートしてくる。このエラーそのものは Codec/Compression/Zlib/Stream.hsc に原因があるらしいが、私は完全に途方にくれてしまった。
私にとって状況を進展させるための唯一の方法は、Haskell の環境からしばらくの間離れてしまうこと(Hugs すら MacPorts でインストール出来ないんだもん)か、まさにそうしようとしていたように、開発の全てを VirtualBox の中の Linux で行うかだった。これは明らかに理想的な状態とは言い難く、GHC の開発者がこの問題を次の GHC のリリースまでに解決してくれていることを望んだ。
最初の問題は、GHC がコンパイルとアセンブルとリンクを 32bit で行うようにすることだ。これは、ghc のスクリプトを修正する上記の作業を含む。そしてそれと同時に、ライブラリの類(例えば、libcurl とか libpq とか)をビルドする際に下記のようなフラグの塊を Setup や cabal に渡すことも要求される。
./Setup configure --ld-options="-arch i386" --gcc-option=-m32
ひょっとすると、--gcc-option=-m32 は不要かもしれない(/usr/bin/ghc ですでに同じ意味のことを書いている)が、その他のオプションはリンカが正しいアーキテクチャを使うように説得するために必須だ。さもないと、リンクに失敗して何も得ることが出来ないか、ひどい場合には壊れたライブラリや実行ファイルが出来上がることになる。同じことが、上記の /usr/bin/ghc の編集に対しても言える。
私が直面した二番目の問題は(なんか Python のパッケージでも同じような問題があったよね)、32bit ライブラリを上手くリンク出来るようにすることだ。これは、もし貴方が拡張ライブラリをリンクしない場合には問題とはならない。が、もしそうでないなら、拡張ライブラリのうちいくつかは Macports でインストールすべきだ。この場合に注意しなければならないのは、リンクしたいライブラリ全てはユニバーサルバリアントのものをインストールしなくてはならないということだ。そうしないと、x86_64 のライブラリしかインストールされず、i386 な Haskell のコードと正しくリンクすることが出来ない。最も簡単な方法は、何かをインストールする前に /opt/local/etc/macports/variants.conf を編集して、+universal を追加することだ。パッケージを全部リビルドするなんて、楽しいことじゃないからね。
もし君がすでに Snow Leopard に移行してて、いろんなものをインストールしているとしたら、全部 universal でリビルドしたいに違いない。上記の編集を行った後に、RoR コミュで紹介されていた方法で、Macports に全てのパッケージを強制的にリビルドさせることが出来る。
sudo port selfupdate sudo port sync sudo port upgrade --force installed
現在 Haskell の習得に挑戦しているのですが、HOC というパッケージの導入で躓いています。はてなダイアリーをはじめ各種ウェブサイトで情報を探したのですが、自力では解決方法を見つけることが出来ませんでしたのでこちらで質問させていただきます。
Mac OS X 10.6.2/GHC 6.12.1(GHC 6.10.4 でも可) の環境で、HOC を導入する手順と、導入作業にあたり注意すべきことを教えてください。GHC6.12.1/GHC6.10.4にて導入を試みた際の作業手順を下にまとめています。間違った点があれば指摘していただけるとありがたいです。
ここで下記のようなエラーが出力され、どうにも自分では解決出来ません。なお、この質問を書いている時点の最新リビジョンは413です。hoc に添付されている README.txt に書いてある通り、『runhaskell Setup configure』も試したのですが、同じエラーが出力されます。
etup.hs:18:19:
Couldn't match expected type `GenericPackageDescription'
against inferred type `Either
GenericPackageDescription PackageDescription'
Expected type: (GenericPackageDescription, HookedBuildInfo)
Inferred type: (Either
GenericPackageDescription PackageDescription,
HookedBuildInfo)
In the `confHook' field of a record
In the second argument of `($)', namely
`defaultUserHooks
{confHook = customConfig, buildHook = customBuild}'
Setup.hs:88:21:
Couldn't match expected type `GenericPackageDescription'
against inferred type `Either
GenericPackageDescription PackageDescription'
Expected type: (GenericPackageDescription, HookedBuildInfo)
Inferred type: (Either
GenericPackageDescription PackageDescription,
HookedBuildInfo)
In the first argument of `configure', namely `pdbi'
In a stmt of a 'do' expression: lbi <- configure pdbi cf
この場合でも同じようにエラーが出力されました。runhaskell configure でもやはり同じようにエラーが出力されます。
エラーメッセージを読む限り、パッケージの依存とか以前のところで Setup.hs がこけているように見えます。(GenericPackageDescriptin 型のデータを受け取る関数に対して Eigher GenericPackageDescription PackageDescription なデータが渡されている?)
誰かしらの知恵というかノウハウを拝借しないと、今のところ自分で解決の方策を立てることが出来ないので、失敗した手順などを書いてみる。
とりあえず、『Snow Leopard では(ghci とかは動くけど)、ghc を使おうとするとエラーが出て動かないよ』という話だけを知っていた。ちょうどウェブの Haskell 界隈を覗いて興味があったので、折角だしということで Haskell を使い始めてみることにした。
なんかここら辺は良くわかってないです。たぶんそんなに変なことはやっていないと思います。
こんな感じに。
Setup.hs:18:19:
Couldn't match expected type `GenericPackageDescription'
against inferred type `Either
GenericPackageDescription PackageDescription'
Expected type: (GenericPackageDescription, HookedBuildInfo)
Inferred type: (Either
GenericPackageDescription PackageDescription,
HookedBuildInfo)
In the `confHook' field of a record
In the second argument of `($)', namely
`defaultUserHooks
{confHook = customConfig, buildHook = customBuild}'
Setup.hs:88:21:
Couldn't match expected type `GenericPackageDescription'
against inferred type `Either
GenericPackageDescription PackageDescription'
Expected type: (GenericPackageDescription, HookedBuildInfo)
Inferred type: (Either
GenericPackageDescription PackageDescription,
HookedBuildInfo)
In the first argument of `configure', namely `pdbi'
In a stmt of a 'do' expression: lbi <- configure pdbi cf
Setup.hs の88行目をやっつけで以下のように書き換えて、再挑戦。
どうも、『GenericPackageDescription が欲しいのに、GenericPackageDescription か HookedBuildInfo のどっちがもらえるか分からない状態だよ』とかそんな意味らしいので、無理やり GenericPackageDescription を渡すようにしてみる感じですね。
customConfig :: (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo
当然ダメ。以下のようなエラーが出る
Setup.hs:1:0:
Warning: In the use of `defaultUserHooks'
(imported from Distribution.Simple):
Deprecated: "Use simpleUserHooks or autoconfUserHooks, unless you need Cabal-1.2
compatibility in which case you must stick with defaultUserHooks"
Compiling HOC_cbits...
In file included from /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/FSEvents.h:28,
from /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/CarbonCore.h:218,
from /System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Headers/AE.h:20,
from /System/Library/Frameworks/CoreServices.framework/Headers/CoreServices.h:21,
from /System/Library/Frameworks/Foundation.framework/Headers/NSURLError.h:17,
from /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:81,
from HOC_cbits/ObjectMap.m:1:
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:51: error: expected specifier-qualifier-list before ‘StgPtr’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:108: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘bdescr’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:163: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:174: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:187: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:198: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:219: error: expected ‘)’ before ‘n’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:223: error: expected ‘)’ before ‘n’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:235: error: expected declaration specifiers or ‘...’ before ‘nat’
/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.4/./include/Block.h:241: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘StgWord’
Setup.hs: Failed in C compilation.
ぐちゃぐちゃやりすぎたので、一旦 Haskell の環境を全部消して入れ直すことに。
そうすると、cabal configure までは行けるようになった。build で同じようにこける点は変わらず。
考えられる対策としては、
1. Cabal を Cabal-1.6.x系統にグレードダウンする
2. Setup.hs を書き換える
のどちらかだと思います。しばらくは1.8に移行していない他のライブラリでも同じエラーが出るのではないかと。
いずれはCabal-1.8系統に対応したモノが増えると思いますので、手間がかかりますが2の手段を執るのが良いと思います。
それならば、Setup.hsの88行目付近の
customConfig :: (Either GenericPackageDescription PackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo
を
customConfig :: (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo
に書き換えると動くのではないかと思います。ただ、ちょっと今Haskellが使えない環境なのでうまくいくかわからないので、もし無理だったら一時的にCabalを1.6に替えるのがよいかと思います。