Ahh, finally recovered my password. I had this entire entry written and was starting to look for links, but lost it as I enabled javascript for livejournal elsewhere on the site and could not find any way to recover the list info. This has happened to me before, and makes me a sad panda. I’m now editing in vim with the intent to copy&paste to the livejournal window. *sigh*
I’ve decided that I like UCW a lot, even though there is a steep learning curve (for me, at least). UCW makes heavy use of CLOS and (non-hygenic) macros, so I’m having to learn a lot about CL that doesn’t necessarily carry over well from scheme.
So let’s start by creating a basic server, as well as some utility functions to allow us to generate various kinds of images. The examples I’ve seen of UCW all seem to exist in the UCW-STANDARD package, sooooo
(in-package :ucw-standard)
The only server component in UCW is named STANDARD-SERVER, but it is capable of utilizing different backends. I create a global variable with an instance of the server class attached to the iolib backend. The other backends include an httpd module as well as a mod_lisp adapter. As iolib is the default development backend and I’m told apache‘s mod_proxy iolib is faster than mod_lisp, we might as well use it.
(defvar *ucw-server* (make-instance 'standard-server :backend (make-backend :iolib :port 9090)))
UCW comes with a standard startup and shutdown pair that takes the server instance as a parameter. I wrap these with trivial funuctions and export them to allow easy use from other packages, such as COMMON-LISP-USER.
(defun startup-thang () (startup-server *ucw-server*)) (defun shutdown-thang () (shutdown-server *ucw-server*)) (export '(startup-thang shutdown-thang))
Next, I have a few SBCL specific functions to generate various image types to allow for faster loading. Note that I do not set up the various hooks, so these cannot be run from a threaded image (such as one where swank or ucw is running). My current approach is to allow the current image to continue running as I invoke a new one to compile, then shutdown the old one and start the new one up. These are explained by the SBCL manual, so I won’t explain them, just toss my source out.
(defun thang-init () (sb-alien:alien-funcall (sb-alien:extern-alien "disable_lossage_handler" (function sb-alien:void))) (swank:create-server) (startup-thang) (sb-impl::toplevel-init)) ; execute the repl (defun save-out-core () (sb-ext:save-lisp-and-die "thang.core")) (defun save-out-auto () (sb-ext:save-lisp-and-die "thang-auto" :executable t :toplevel 'thang-init)) (defun save-out () (sb-ext:save-lisp-and-die "thang" :executable t))
As well as a UNIX Makefile to wrap around the image generation commands.
.PHONY : clean all: thang-auto clean: rm -vf *.fasl thang.core thang thang-auto SRC=thang.lisp thang.core: $(SRC) sbcl --eval "(require 'thang)" --eval "(ucw::save-out-core)" thang: thang.core sbcl --core thang.core --eval "(ucw::save-out)" thang-auto: thang ./thang --eval "(ucw::save-out-auto)"