Common LispでCaveman2を起動する

他のプログラム言語でできることは、Common Lispでも大抵できる。例えばCaveman2は、Common Lisp上で動作するWebフレームワーク。
私はCommon Lispに関しては初心者だが、Caveman2を起動させるまでにはかなり苦労し、途中何度も心が折れそうになった。暗黙の了解のような「罠」があちこちに仕掛けられているような気がした。
ここではCommon LispのインストールからCaveman2の起動が一通り動かせるようになるまで、一連の経緯を備忘録として記すことにする。

まずはまったく最初から、Common Lispさえインストールされていない状態からスタートする。

環境

Linux Centos 7.4

Roswellのインストール

Common LispをインストールするというのにいきなりRoswellなる言葉が出てきて恐縮である。Common LispSBCL (Steel Bank Common Lisp) を直接インストールするのもよいが、ここではまずRoswellというツールを導入する。後になってバージョン管理で苦労しないように、Roswellがオススメ。

インストールには本当はyumを使いたかったのだが、Roswellのサイトを見てもよくわからなかったのでソースコードからビルドした。最新のRoswellが使えるし。具体的にはRoswellの「Building from Source」を参考にした、というかほぼコピペ。

まず適当な作業用ディレクトリを作成する。私はよく「~/Downloads」ディレクトリ上で作業する。

$ cd  <- ホームディレクトリへ移動
$ mkdir Downloads
$ cd Downloads
$ sudo yum groupinstall "Development Tools"
$ sudo yum install libcurl-devel zlib-devel
$ git clone -b release https://github.com/roswell/roswell.git
$ cd roswell
$ sh bootstrap
$ ./configure
$ make
$ sudo make install

以上で、/usr/local/binにrosが作成される。「ros」とはRoswellのこと。

SBCLのインストール

Roswellを「setup」すると、SBCLがインストールされる。どこで実行してもよい。

$ ros setup

これでSBCLがインストールされる。2018/5月現在、SBCLのバージョンは1.4.7だった。

clackのインストール

Caveman2を動かすためにはclackと呼ばれるツールが必要になるらしい。先ほどインストールしたRoswellを使ってclackをインストールする。Roswellの実力がここから発揮される。ちなみにこれもどのディレクトリ内で実行してもよい。

$ ros install clack

こうすると、~/.roswell/binディレクトリにclackupという名前のツールがインストールされる。~/.bashrcファイルを編集して、~/.roswell/binにパスを通す(私はここでPATHを設定することに気づかず引っかかった)。

$ echo "export PATH=$HOME/.roswell/bin:$PATH" >> ~/.bashrc
$ source ~/.bashrc

プロジェクトディレクトリを作成する準備

プロジェクトディレクトリを作成する場所を確保する。どこに作成してもよいが、ここでは例として~/work/sbclディレクトリとする。プロジェクトディレクトリは、さらにこの中に作成される。

$ mkdir -p ~/work/sbcl
$ cd ~/work/sbcl

Caveman2の導入

いよいよCaveman2を入れる。

SBCLをREPL(Read-Eval-Print Loop、いわゆる対話モード。例えばPythonの場合シェル上で「python」と入力するのと同じ。)で起動する。先ほど作成したディレクトリ上で「ros run」と入力する。Roswellはモジュール管理だけでなくこんなこともできる。

$ cd ~/work/sbcl
$ ros run
(ここからはSBCL内。先頭の*はプロンプト。)
* (ql:quickload :caveman2)  ←最初に実行したときはダウンロードで時間がかかる
* (caveman2:make-project #P"myapp" :author "kitemw")"myapp""kitemw"はお好みで。
(CTRL+DでSBCLを終了)

上のmake-projectを実行すると、カレントディレクトリ上にmyappディレクトリが作成され、その中を見るとCaveman2実行に必要なひと通りのファイルが作成されているわかる。

プロジェクトディレクトリをquicklispに認識させる

make-projectでただプロジェクトディレクトリを作成しただけでは駄目で、Common Lispに(というかquicklispというバージョン管理ツールに?)~/work/sbcl/myappディレクトリを認識させる必要がある。私はここで引っかかり、次のCaveman2実行で「System "myapp" not found」というエラーが出て先に進めず、解決に相当時間がかかった。

具体的には、~/.roswell/local-projectsというディレクトリに、myappディレクトリのシンボリックリンクを置けばよい。

$ ln -s ~/work/sbcl/myapp ~/.roswell/local-projects/myapp

Caveman2を起動する

Caveman2を実行するには、~/work/sbcl/myappディレクトリ上で、次のコマンドを入力する。

$ cd ~/work/sbcl/myapp
$ APP_ENV=development clackup --port 8000 app.lisp

ずらずらと画面に表示されるが、最後に次の2行が表示されたらきちんと動いている。

Hunchentoot server is going to start.
Listening on localhost:8000.

実際に起動しているかどうか確認する。別の端末で、

$ curl http://127.0.0.1:8000

HTMLの中身が表示されたら成功。もちろんブラウザで確認してもよい。
なお、Caveman2を毎回起動するたびに"APP_ENV=..."を入力するのは面倒なので、私は「run」という名前のシェルスクリプトをプロジェクトディレクトリ内に作って実行している。

$ echo "APP_ENV=development clackup --port 8000 app.lisp" > run
$ chmod 0777 run
$ ./run

まとめ

以上、Common Lispの初心者がWebフレームワークCaveman2を起動するところまで一気に説明したが、いかがだっただろうか? ここまでうまくいったら、あとはファイルの中身を調べてカスタマイズするのも思いのまま。Railsでの環境もそうだけど、やっぱり最低限の動作を確認できると安心感が違うよね。

次はCaveman2でデータベースsqlite3あたりを使う方法を調べてみたい。