Creating standalone executables to be distributed on various platforms.
All modern Lisp compilers can create executables to be distributed to users. This page covers how to build executables under various implementations, and how to package and distribute them for various OSes.
Make sure everything works. Try an example; see the game run. If the game does not run properly, troubleshoot, otherwise continue.
> (asdf:operate 'asdf:load-op :lispbuilder-sdl-examples) ... lots of loading text ... NIL > (sdl-examples:mandelbrot) NIL
The guide assumes a Unix-like command-line environment. It is not strictly necessary to use such an environment for development, although it may make your life easier (in more ways that one). Feel free to use batch commands or Power Shell, but be aware that you may have to translate some simple shell commands.
When creating an executable, a user-defined function can be provided to run when the Lisp image starts up. Users of LISPBUILDER-SDL typically use this function to load and initialize SDL and start their game. An example of such a function follows;
(defun main ()
The function looks for a foreign library called SDL (e.g. "SDL.dll"), and loads the library. Then it starts one the examples in LISPBUILDER-SDL. When the example demo ends, it quits the program (to avoid entering the toplevel, as some Lisps do).
Type the above function into a file called "main.lisp" for use below.
Executables, or Lisp images, are executable copies of the runtime state of the compiler after loading user-defined code. Some Lisp compilers, especially commercial ones, try to slim down the resulting executable, but in open source compilers, an image will include the entire compiler.
To dump an executable, first start the compiler and load LISPBUILDER-SDL and any user code. After defining a startup function (more details below), run the following commands to create the binary.
> (asdf:operate 'asdf:load-op :lispbuilder-sdl) ... NIL > (load (compile-file "main")) ... NIL > (let ((filename #+windows "main.exe" #-windows "main")) #+clisp (saveinitmem filename :init-function #'main :executable t :norc t) #+sbcl (save-lisp-and-die filename :toplevel #'main :executable t) #+clozure (save-application filename :toplevel-function #'main :prepend-kernel t))
Theoretically, this executable can just be run by itself,
$ ./main # or main.exe on Windows
but, more often than not, the necessary runtime components (shared libraries, graphics, etc) are not in correct locations relative to the executable. Therefore, for most applications, it will be necessary to build a distribution to run on each target platform.
The easiest way to find runtime libraries is simply to put them in the same directory as the binary. For example;
$ mkdir build $ cp main build
Find SDL.dll (on Windows), libSDL.so (on Linux), or SDL.framework (on OS X), and copy it to the build folder.
$ cp C:\\path\\to\\SDL.dll build # Windows $ cp /usr/lib/libSDL.so build # Linux $ cp /Library/Frameworks/SDL.framework build # OS X
And copy and runtime libraries required by the compiler itself. For example, on CLISP;
$ cp C:\\path\\to\\clisp\\*.dll # CLISP
Finally, copy and graphics or other resources to the build folder. Now try running the game;
If it works, copy the folder over to another machine (preferably one without Lisp or SDL installed), and try running it. If it works there too, then you can tar it, zip it, make a Mac app for it, or make a Windows installer for it, etc.
One problem with the provided startup function is that expects to find a shared library called "SDL". This doesn't work on Linux where the file is traditionally "libSDL.so", or on OS X, where most users would prefer to use "SDL.framework". The following snippets, taken from the source code of LISPBUILDER-SDL, can be used as portable substitutes for the above.
(cffi:define-foreign-library sdl (:darwin (:or (:framework "SDL") (:default "libSDL"))) (:windows "SDL.dll") (:unix (:or "libSDL-1.2.so.0.7.2" "libSDL-1.2.so.0" "libSDL-1.2.so" "libSDL.so" "libSDL")))