‘How do I create a Lisp application binary without including Quicklisp or Qlot?’
Quicklisp helps you work faster because it knows where to find libraries and Qlot keeps you mostly out of dependency hell. Without these two tools application development would be dead slow. However, applications distributed as standalone binaries should not contain them.
Quicklisp adds unnecessary code and it will likely try to create a
~/quicklisp directory on your user’s machine. This can fail for any
number of reasons (such as file permissions or lack of internet access) which
will only cause headaches.
Qlot also adds unnecessary code and it will cause the same problems as Quicklisp.
The process of building a binary using Buildapp and Quicklisp without actually having them inside the final application is as follows:
- Load your project using the normal Quicklisp method,
- Export a manifest file which lists the absolute path to every ASDF system
currently loaded into the Lisp image. This is done using
- Exit from Lisp.
- Use Buildapp to create your binary. The manifest file must be passed as a
--load-systemmust be used to load your system and Quicklisp must NOT be loaded.
When Qlot is employed in a project, the above process becomes:
- Load Qlot.
- Load your project using Qlot’s method, i.e.
- Export the manifest file using
- Exit from Lisp.
- Use Buildapp to create your binary.
Since Quicklisp is not aware of Qlot
(ql:write-asdf-manifest) must be
(qlot:with-local-quicklisp) in order to generate paths to
the project-local Qlot managed libraries instead of the system wide Quicklisp
This is an excerpt of a makefile from a project which uses Qlot. The makefile
is used to create a standalone binary that does not contain
Quicklisp or Qlot. The
prep-quicklisp.lisp script is
used to setup Quicklisp for loading the project system from an
# CCL Flags for manifest build MANIFEST_FLAGS = --no-init MANIFEST_FLAGS += --batch MANIFEST_FLAGS += --load prep-quicklisp.lisp MANIFEST_FLAGS += --eval '(ql:quickload :qlot)' MANIFEST_FLAGS += --eval '(qlot:install :$(QL_SYSTEM))' MANIFEST_FLAGS += --eval '(qlot:quickload :$(QL_SYSTEM))' MANIFEST_FLAGS += --eval '(qlot:with-local-quicklisp :$(QL_SYSTEM) (ql:write-asdf-manifest-file \#P"$(MANIFEST)" :if-exists :supersede :exclude-local-projects nil))' MANIFEST_FLAGS += --eval '(quit)' # Buildapp settings B_FLAGS = --output $(OUTDIR)/$(TARGET) B_FLAGS += --manifest-file $(MANIFEST) B_FLAGS += --load-system $(QL_SYSTEM) B_FLAGS += --entry app:main make_manifest: $(LISP) $(MANIFEST_FLAGS) make_app: $(BUILDAPP) $(B_FLAGS)