読者です 読者をやめる 読者になる 読者になる

Status Code 303 - See Other

Java, C, C++, C#, Objective-C, Swift, bash, perl, ruby, PHP, Python, Scala, Groovy, Go, DevOps, Raspberry Pi など。情報の誤りや指摘・意見などは自由にどうぞ。

Haskell を cygwin 上で動かすのに苦労した話

Haskell 環境構築

概要

Haskell の動作環境を用意する。cygwin上で動かそうとすると少し苦労したのでメモ。

インストーラのダウンロード

以下をURLから、Windows版のHaskell Platform のインストーラのうち環境に適したものをダウンロード。
Download Haskell Platform
なお、私がダウンロードしたのは、Full(64bit)版。

インストール

指示に従っていけば特に問題なし。パスもインストーラが作成してくれる。

Cygwin で ghci 起動

cygwin を起動して、ghci(対話モードのインタプリタ)を起動してみると・・。

$ ghci
WARNING: GHCi invoked via 'ghci.exe' in *nix-like shells (cygwin-bash, in particular)
         doesn't handle Ctrl-C well; use the 'ghcii.sh' shell wrapper instead
GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help
Prelude>

こんなメッセージが表示される。
警告に書いてある通り、Ctrl + C を用いると、プロンプトは出てくれるのだがそこから何も入力できなくなる。
関連プロセス(ghc.exe)はなぜか生存中。このプロセスをタスクマネージャから強制終了すると入力ができるようになる。

これを防ぐために、ghciコマンドで起動している「ghci.exe」ではなく、「ghcii.sh」が起動するように変更する。
このファイルは「(プログラムフォルダ)\Haskell Platform\8.0.1\bin」に存在ある。
「ghcii.sh」→「ghci」にリネームする。そうすると、「ghci.exe」より優先度が高くなり、シェルの方を呼び出してくれる。

変更すると以下のようになる。

$ ghci
GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help
Prelude>

ghcコンパイルできなかった

Haskell のソースファイルをghcを使ってバイナリにコンパイルするときに、私の環境では失敗した。

$ ghc fizzbuzz.hs -o fizzbuzz
Linking fizzbuzz.exe ...
fd:5: hGetContents: invalid argument (invalid byte sequence)
ghc.exe: fd:5: hGetContents: invalid argument (invalid byte sequence)

もう一回起動してみると、なぜかメッセージが変わった。

$ ghc fizzbuzz.hs -o fizzbuzz
Linking fizzbuzz.exe ...
realgcc.exe: error: s\Java\▒▒▒K: No such file or directory
P:\Program Files\Haskell Platform\8.0.1\lib/../mingw/bin/windres.exe: "P:\Program Files\Haskell Platform\8.0.1\lib/../mingw/bin/gcc.exe ▒̓X▒e▒[▒^▒X 1 ▒ŏI▒▒▒▒▒܂▒▒▒
`windres.exe' failed in phase `Windres'. (Exit code: 1)

今度は文字化けが発生。
エラーメッセージを調べていたら、
「LANG=C.utf-8 stack build works as intended.」(stack build は環境変数 LANGがC.utf-8だったら意図したとおりに動いてるよ)
とかあったので、文字化けも考慮して、LANGを確認。

$ echo $LANG
ja_JP.UTF-8

C.UTF-8に変更。

$ export LANG='C.UTF-8'

$ echo $LANG
C.UTF-8
$ ghc fizzbuzz.hs -o fizzbuzz
Linking fizzbuzz.exe ...
$ ./fizzbuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
(省略)

動いた!...でも。これが本当に原因か分からないので、動作検証。元に戻してみる。

$ export LANG='ja_JP.UTF-8'

$ echo $LANG
ja_JP.UTF-8
$ touch fizzbuzz.hs
$ ghc fizzbuzz.hs -o fizzbuzz
[1 of 1] Compiling Main             ( fizzbuzz.hs, fizzbuzz.o )
Linking fizzbuzz.exe ...
realgcc.exe: error: icrosoftw▒E
                               ▒▒: Invalid argument
P:\Program Files\Haskell Platform\8.0.1\lib/../mingw/bin/windres.exe: "P:\Program Files\Haskell Platform\8.0.1\lib/../mingw/bin/gcc.exe ▒̓X▒e▒[▒^▒X 1 ▒ŏI▒▒▒▒▒܂▒▒▒
`windres.exe' failed in phase `Windres'. (Exit code: 1)

・・・ってことで、これが原因らしい。
なお、touchコマンド使っているのは、ghc は内部でソースファイル、オブジェクトファイルの更新時間を見てるようで、
タイムスタンプ更新しないとコンパイルしてくれないため。

ラッパースクリプトを .bashrc に追加。

毎回 Haskell のためだけに環境設定いじるのが微妙だったり面倒だったりする場合は、cygwin 起動時に読み込まれる「~/.bashrc」に
以下のようにラッパースクリプトを作成する。これだと、ghc を使用するときのみLANGを変更してくれる。

GHC_PATH='which ghc'
function ghc() {
  local LANG='C.UTF-8'
  "$GHC_PATH" $@
}