I'm working on a web app using Hunchentoot (on SBCL and Linux), and usually I just run it from Emacs (SLIME), but for deployment I want something that's easier to automate. So I'm trying to figure out ASDF, because that seems to be what everybody's using these days.
myapp.asd:
(in-package #:asdf)
(defsystem :myapp
:name "my app"
:depends-on ("hunchentoot")
:components ((:file "package")
(:file "server" :depends-on ("package"))))
package.lisp:
(defpackage myapp
(:use :cl))
server.lisp:
(setq hunchentoot:*dispatch-table*
(list (hunchentoot:create-static-file-dispatcher-and-handler "/foo" "foo")))
(hunchentoot:start-server :port 8705)
If I try loading it by hand:
$ sbcl
* (require 'asdf)
* (asdf:operate 'asdf:load-op 'myapp)
it loads and compiles a whole bunch of functions, but then just stops. Hunchentoot isn't running, and the prompt doesn't accept input. I don't know what state it thinks it's in: the last lines printed are:
STYLE-WARNING: Implicitly creating new generic function STRINGIFY-COOKIE.
STYLE-WARNING: Implicitly creating new generic function DISPATCH-REQUEST.
STYLE-WARNING: Implicitly creating new generic function WRITE-HEADER-LINE.
Is there a way to make this work? (Confession: I really don't understand ASDF or Common Lisp packages very well at all, despite many hours of reading about them.)
Many (not all) Lisp implementations support a save-image (or save-world or dump) mechanism that will encapsulate a body of code and run functions at startup. As another poster said, these mechanisms are platform- and vendor-specific.
Most Lisp implementations (all?) have a command-line interface. So a conventional approach to deploying a Lisp application is to wrap a shell script around Lisp. The script must set up the program environment and pass command line arguments. Typically the runtime context includes application files to load (via ASD or LOAD-FILE) and one or more forms to evaluate or functions to run.
You can roll your own script, or you can re-use some existing technology. Take a look at clbuild which is useful for several reasons. (See below for more about clbuild functionality and portability.)
You can extend clbuild to run your own application with command line arguments. For example, to load the "myapps" system and run the function "myapp1:start" you would invoke clbuild as follows:
clbuild run any :myapps "\\(myapp1:start 1 2 3\\)"
Note the character escape syntax for parentheses; this is needed for most command interpreters.
An alternative approach is to redirect standard input from a file. For example:
clbuild run any :myapps < commands.lisp
clbuild is most commonly used to install and run open source CommonLisp libraries.
It is a bash script, so it is highly portable. The download facility relies on programs like CVS, Subversion, darcs, git, and Mercurial.
By default clbuild runs sbcl but it is very easy to configure it to run another Lisp such as (shameless plug) Clozure CL (ccl). Copy clbuild.conf.default
to clbuild.conf
and edit clbuild.conf
to point to the Lisp executable you want to use.
Your example works for me, at least modified to work with current Hunchentoot 1.0.0, but that is merely change of (hunchentoot:start-server :port 8705)
to (hunchentoot:start (make-instance 'hunchentoot:acceptor :port 8705))
.
In any case, while possible, you are not really supposed to run things from inside files loaded by ASDF. It serves a role analogous to a build system, and I don't think having make
launch a webserver is exactly common...
For deployment see cl-launch, sbcl command-line options, in particular --eval
, or saving an image.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With