八発白中

技術ブログ、改め雑記

プロジェクトごとに使うQuicklispを分離する

何か作った〜、とかの記事しか書かないので、もうちょっと小粒のTipsっぽいのも書いておこうかなと思った。

問題点

複数のCommon Lispアプリケーションを同じマシンで動かしているときに困るのが、Quicklisp。Quicklispは基本的にユーザ単位でインストールするので、複数のアプリケーションで共通のバージョンのを使わないといけなくなる。

この方式で問題なのは、一方のライブラリでは最新のdistを使いたいけど、もう一方のライブラリでは古いまま使い続けたい、というとき。

複数のアプリケーションを同じサーバで動かすときとかql:update-all-distsするだけでプロジェクトが動かなくなるのでそういう事故を避けるためにもプロジェクトごとにQuicklispを分けたい。

そこで、RubyのBundlerやPerlのCartonみたいに、プロジェクトルートにQuicklispインストールしてそれを使うみたいなことできないかなー、と思って試してみた。

今回は、マイブームのShellyを使っている。

1. Quicklispをインストール

プロジェクトルートにQuicklispをインストール。公式でおすすめされている「wgetしてloadして〜」とかやるのだるいので、僕はワンライナー書いてインストールしてる。

$ (curl -L http://beta.quicklisp.org/quicklisp.lisp && echo '(quicklisp-quickstart:install :path #P"quicklisp/")') | ccl --no-init

これはClozure CLだけど、SBCL派の人はsbcl --no-userinitに置き換えればそのまま動くと思う。

--no-initをつけないとインストール済みだよって怒られるのでつける必要がある。

2. プロジェクトのQuicklispを使う

プロジェクトルートのQuicklispを使うには、ただql:*quicklisp-home*をセットするだけ。

shlyfileに以下のコードを記述する。

(setf ql:*quicklisp-home* (asdf::truenamize #P"quicklisp/"))

これでプロジェクトルートでshlyコマンドを実行するときは必ずプロジェクトローカルなQuicklispを使うようになる。

3. 依存モジュールインストール

何も特別なことはなく、ql:quickload すれば依存モジュールがプロジェクトローカルにインストールされる。

$ shly ql:quickload :myapp

プロジェクトローカルのQuicklispのアップデートするには

こちらも特別なことはなくて、以下のコマンドを実行する。

$ shly ql:update-all-dists --prompt nil

Swankサーバ起動

コマンドラインではこれで良いけど、SLIMEで使いたい、という場合は、shlyfileに以下のようなタスクを記述しておく。

(defun start-swank (&key (port 4005))
  (swank:create-server :port port))

するとプロジェクトルートでshly start-swankできるようになる。

$ shly start-swank --port 4005
;; Swank started at port: 4545.

4545

これでSwankサーバが立ち上がったので、Emacsで M-x slime-connect 127.0.0.1 4005 すれば繋がる。