私の使用している「さくらのレンタルサーバ スタンダード」は FreeBSD 9.1-RELEASE-p24 amd64 という環境です。root 権限はないものの、ディスクスペースは 100GB あるので、ここに ghc、cabal-install を導入して、Haskell が動作する環境を整えます。
以下のブログエントリが大変参考になりました。
ghc 導入
結論から言うと、2015 年 12 月時点の最新 ghc-7.10.x は root 権限がないと導入が難しいです。なので今回は ghc-7.8.x 系の最新版である ghc-7.8.4 を導入しました。
.bash_profile
は以下のようにしておきます。
alias cabal='TMPDIR=~/.tmp LANG=en_US.UTF-8 cabal'
export PATH=$HOME/usr/bin:$PATH
export PATH=$HOME/.cabal/bin:$PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/rts-1.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/ghc-prim-0.3.1.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/integer-gmp-0.5.1.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/base-4.7.0.2
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/filepath-1.3.0.2
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/array-0.5.0.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/deepseq-1.3.0.2
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/bytestring-0.10.4.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/containers-0.5.5.1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/old-locale-1.0.0.6
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/time-1.4.2
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/unix-2.7.0.1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/directory-1.2.1.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/process-1.2.0.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/hpc-0.6.0.1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/pretty-1.1.1.1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/template-haskell-2.9.0.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/Cabal-1.18.1.5
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/binary-0.7.1.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/bin-package-db-0.0.0.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/hoopl-3.10.0.1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/transformers-0.3.0.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/xhtml-3000.2.1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/terminfo-0.4.0.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/haskeline-0.7.1.2
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/ghc-7.8.4
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/old-time-1.1.0.2
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/haskell98-2.0.0.3
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/${HOME}/usr/lib/ghc-7.8.4/haskell2010-1.1.2.0
cabal の alias を指定しています。cabal がパッケージをビルドする際に、デフォルトで /var/tmp
が使用されるのですが、これが時々以下のようなエラーを吐きます。
$ cabal install --only-dependencies
...(snip)
checking whether we are cross compiling... configure: error: in `/var/tmp/cabal-tmp-8769/network-2.6.2.1':
...(snip)
cabal: Error: some packages failed to install:
network-2.6.2.1 failed during the configure step. The exception was:
ExitFailure 1
これを $HOME/.tmp
を指定することで回避しています。
ghc のインストール先は $HOME/usr
に指定するのですが、ghc ビルド時にライブラリが見つからないというエラーを、上記のように LD_LIBRARY_PATH
を指定しておくことで回避します。ついでに ghc と cabal のインストール先にも PATH を通しておきます。
もし、ghc や cabal を何度か導入しようとして挫折したことがある場合、.ghc
や .cabal
が存在するかも知れません。これらは消しておかないとトラブルの元になる可能性があります。
$ rm -rf ~/.ghc ~/.cabal
環境がきれいになったところで ghc を以下のようにインストールします。
$ wget -c --no-check-certificate https://www.haskell.org/ghc/dist/7.8.4/ghc-7.8.4-x86_64-portbld-freebsd.tar.xz
$ tar xf ghc-7.8.4-x86_64-portbld-freebsd.tar.xz
$ cd ghc-7.8.4
$ ./configure --prefix=$HOME/usr
$ gmake install
これで ghc が使用できるようになります。
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.8.4
簡単なコードならコンパイルして実行することも可能です。
$ echo 'main = putStrLn "hello"' > hello.hs
$ ghc hello.hs
[1 of 1] Compiling Main ( hello.hs, hello.o )
Linking hello ...
$ ./hello
hello
cabal-install の導入
ghc だけでは何もできないので、cabal-install を導入します。cabal-install は最新の 1.22.6.0 が導入できました。
$ curl -O http://hackage.haskell.org/package/cabal-install-1.22.6.0/cabal-install-1.22.6.0.tar.gz
$ tar xf cabal-install-1.22.6.0.tar.gz
$ cd cabal-install-1.22.6.0
$ vi bootstrap.sh
bootstrap.sh
を実行する前に、以下のように修正する必要があります。
+ LINK=/usr/bin/ld
+ #LINK="$(for link in collect2 ld; do
+ # echo 'main;' | ${CC} -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -qw $link &&
+ # echo 'main;' | ${CC} -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -w $link |
+ # sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
+ #done)"
- LINK="$(for link in collect2 ld; do
- echo 'main;' | ${CC} -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -qw $link &&
- echo 'main;' | ${CC} -v -x c - -o /dev/null -\#\#\# 2>&1 | grep -w $link |
- sed -e "s|\(.*$link\).*|\1|" -e 's/ //g' -e 's|"||' && break
- done)"
要するに環境から適切な ld コマンドを探しだしている部分を、LINK=/usr/bin/ld
と決め打ちにしています。これを行わないと、'/usr/bin/ld""--eh-frame-hdr""-V""-dynamic-linker""/libexec/ld' does not refer
という不可解な結果が LINK
に入ってしまい、スクリプトがこけます。
修正を行ったら、以下のように実行します。
$ TAR="tar -f -" ./bootstrap.sh --no-doc
結構時間がかかりますが、お茶でも飲みながら待ちます。
$ cabal --version
cabal-install version 1.22.6.0
using version 1.22.4.0 of the Cabal library
コードを書く
こんな感じで始めます。
$ mkdir foo
$ cd foo
$ cabal sandbox init
$ cabal init
最近は cabal
よりも stack
を使うのが主流になってきているようですが、stack
は動向が激しいので、落ち着くまでは枯れた cabal
を使用します。
補足
2018 年 10 月に確認したところ、Stack の FreeBSD 版バイナリ が公開されていたため、こちらを動作させることができないか検証してみましたが無理でした。
- 必要なライブラリが多数存在しない(ライブラリを個別にビルドすればできなくはない)
- FreeBSD 9.1 に存在しないシステムコールを使用している
いくつかの足りないライブラリを解決していき、引数なしの stack
コマンドが動作するようにはなったものの、stack setup
を実行すると「存在しないシステムコール: 12」というエラーメッセージが表示されてしまい、お手上げでした。Stack のサイトにも FreeBSD 11 以降と記載さてているため、システム構成が古いさくらのレンタルサーバでは GHC 7.8.4 を Cabal で運用するのが限界そうです。