пятница, 7 мая 2010 г.

Как я ставил RULISP


История установки RULISP для изучения.


Предварительные условия: у меня на машине с Gentoo установлен свежий SBCL (1.0.38.gentoo-r0), в портеж добавлен оверлей gentoo-lisp-overlay, из которого я буду ставить большинство пакетов CL. Также из портежа поставлен PostgreSQL 8.4 для базы данных форума.

Использовалась инструкция по установке отсюда.

Этап 1. Подготовка

  • Для начала я создал рабочую директорию ~/workspace/lisp - здесь будут находиться пакеты, необходимые для запуска RULISP.
  • В эту директорию загрузил следующие пакеты с гитхаба: cl-closure-template, cl-pdf, cl-recaptcha, cl-routes, colorize, garbage-pools, puri-unicode, restas, restas-colorize, restas-directory-publisher, restas-forum, restas-planet, restas-simple-auth, restas-wiki, rulisp.
  • Создал директорию ~/workspace/lisp/systems для добавления пакетов в ASDF.
  • Сделал симлинки на все файлы *.asd из загруженных пакетов.
  • В ~/.sbclrc прописал строчку для того, чтобы установленные пакеты были доступны в ASDF:
    (push (merge-pathnames "workspace/lisp/systems/" (user-homedir-pathname)) asdf:*central-registry*)
    
  • Создал от рута директории /var/cache/rulisp (для кэша планеты) и /var/rulisp (здесь будут храниться данные для вики). Так как я буду запускать программу от своего имени, то сделал chown на эти директории.
  • Скачал http://pcl.catap.ru/snapshot.zip и распаковал файлы из содержащейся в нем директории /var/www/pcl.catap.ru/htdocs/data/pages/pcl/ в /var/rulisp/pcl - это страницы dokuwiki для отображения в разделе PCL. В файле rulisp/pref.lisp исправил строчку, указывающую на расположение страниц PCL:
    (defparameter *pcl-dir* #P"/var/rulisp/pcl/")
    
  • Чтобы не мучиться с зависимостями пакетов, имея оверлей gentoo-lisp-overlay, я просто поставил оттуда пакет restas - он вытянул все необходимые для компиляции пакеты, а моя настройка в ~/.sbclrc заставляет SBCL использовать версии пакетов из гита. (Как вариант можно во время компиляции получать ошибки вида "пакет XXX не найден" и тут же бежать в консоль его ставить. Но это неинтересно :).

Этап 2. Создание базы


Postgres у меня уже был настроен, так что я запустил psql и создал базу rulisp:
$ psql
> create database rulisp;
Далее нужно было создать структуру базы, я воспользовался скриптами из директории rulisp/install:
> \i ~/workspace/rulisp/install/user.sql
> \i ~/workspace/rulisp/install/forum.sql
> \i ~/workspace/rulisp/install/format.sql
На файле forum.sql я получил ошибку вида:
psql:forum.sql:83: ERROR:  language "plpgsql" does not exist
Как выяснилось - для хранимых функций требуется поддержка языка PgPlSQL. Чтобы её добавить, выполнил от имени пользователя postgres следующую команду:
> create procedural language pgplsql;
Теперь повторный запуск скрипта forum.sql выполнился весь. Осталось выполнить скрипты обновлений users.update-01.sql, users.update-02.sql, forum.update-1.sql и format.update-01.sql.
В последнюю очередь исправил в файле rulisp/pref.lisp строчку с параметрами подключения к базе данных (второе значение - имя пользователя, а третье я оставил пустым, так как запускаю из-под того же пользователя):
(defparameter *rulisp-db* '("rulisp" "lisp" "123" "localhost"))

Этап 3. Запуск


Запускал RULISP конечно же в Emacs со SLIME-ом. SLIME тоже взял с гита. Выполнил загрузку пакета rulisp:
CL-USER> (asdf:oos 'asdf:load-op :rulisp)
Подождал немного, пока оно собирается и... получил странное сообщение:
erred while invoking #<COMPILE-OP NIL {1003B3B5D1}> on
#<CL-SOURCE-FILE "pcl" {10047DBF01}>
Мучился я с ним недолго - такое уже бывало раньше при большом изменении пакетов. Я просто удалил FASL-ы из ~/.fasls и запустил сборку еще раз. Теперь все прошло хорошо.

Наконец-то :) запустил движок:
CL-USER> (restas:start '#:rulisp :port 8080)
Открыл в браузере http://localhost:8080 и получил что-то очень знакомое. :) Побродил по страницам и разок выскочила ошибка Internal Server Error 500. Чтобы посмотреть что происходит установил отладочный параметр:
CL-USER> (setf hunchentoot:*catch-errors-p* nil)
Теперь в случае ошибок в Emacs выскакивает отладчик. Можно поглядеть содержимое переменных с помощью инспектора по C-c I.

Заключение


Теперь в моей рабочей директории целая куча репозиториев, которые надо периодически синхронизировать. Чтобы меньше трудиться, написал простой скрипт для обновления update.sh:
#!/bin/sh

# Сначала обновляем все локальные репозитории
for i in `find . -maxdepth 1 -mindepth 1 -type d`; do
        if [ -d "${i}/.git" ]; then
                echo "******* Обновление пакета ${i}"
                cd $i
                git pull
                cd ..
        fi
done

# Теперь собираем образ SBCL со SWANK
sbcl --noinform --noprint --disable-debugger --eval \
"(progn (load \"/home/maestro/workspace/lisp/slime-archimag/swank-loader.lisp\")\
 (save-lisp-and-die \"/home/maestro/.emacs.d/sbcl.core-for-slime\"))"
И положил этот скрипт в директорию ~/workspace/lisp/ - скрипт обходит все поддиректории и проверяет, есть ли в них .git, а потом вызывает git pull для обновления. Потом производится сборка образа SBCL для быстрой загрузки в Emacs.