Building and Distributing Stand-alone Executables

For all compilation modes, the output of mzc relies on MzScheme (and MrEd) to provide run-time support to the compiled code. However, mzc can also package code together with its run-time support to form an executable that works on the source machine or a package that can be distributed to other machines.

5.1  Stand-Alone Executables from Scheme Code

The command-line flag --exe directs mzc to embed a module (from source or byte code) into a copy of the MzScheme executable. (Under Unix, the embedding executable is actually a copy of a wrapper executable.) The created executable invokes the embedded module on startup. The --gui-exe flag is similar, but it copies the MrEd executable.

If the embedded module refers statically (i.e., through require) to modules in MzLib or other collections, then those modules are also included in the embedding executable.

Library modules or other files that are referenced dynamically -- through eval, load, or dynamic-require -- are not automatically embedded into the created executable. Such modules can be explicitly included using mzc's --lib flag. Alternately, use the forms of the runtime-path.ss MzLib library to embed references to the run-time files in the executable; the files are then copied and packaged together with the executable when creating a distribution (as described in the following section).

Modules that are implemented directly by extensions -- i.e., extensions that are automatically loaded from (build-path "compiled" "native" (system-library-subpath)) to satisfy a require -- are treated like other run-time files: a generated executable uses them from their original location, and they are copied and packaged together when creating a distribution.

The --exe and --gui-exe flags work only with module-based programs. The embed.ss library in the compiler collection provides a more general interface to the embedding mechanism.

Example:

mzc --gui-exe hello hello.ss

Under Windows, this command produces hello.exe, which runs the same as invoking the hello.ss module. Under Mac OS X, the resulting executable is an application hello.app.

A stand-alone executable is ``stand-alone'' in the sense that you can run it without starting MzScheme, MrEd, or DrScheme. However, the executable depends on MzScheme and/or MrEd shared libraries, and possibly other run-time files declared via runtime-path.ss. The executable can be packaged with support libraries to create a distribution, as described in the following section.

5.2  Distributing Stand-Alone Executables

The command-line flag --exe-dir directs mzc to combine a stand-alone executable (created via --exe or --gui-exe) with all of the shared libraries that are needed to run it, along with any run-time files declared via the runtime-path.ss MzLib library. The resulting package can be moved to other machines that run the same operating system.

After the --exe-dir flag, supply a directory to contain the combined files for a distribution. Each command-line argument is an executable to include in the distribution, so multiple executables can be packaged together:

Example:

mzc --exe-dir geetings hello.exe goodbye.exe

Under Windows, this example creates a directory greetings (if the directory doesn't exist already), and it copies the executables hello.exe and goodbye.exe into greetings. It also creates a lib sub-directory in greetings to contain DLLs, and it adjusts the copied hello.exe and goodbye.exe to use the DLLs in lib.

The layout of files within a distribution directory is platform-specific:

A distribution also has a collects directory that is used as the main library collection directory for the packaged executables. By default, the directory is empty. Use the ++copy-collects flag to supply a directory whose content is copied into the distribution's collects directory. The ++copy-collects flag can be used multiple times to supply multiple directories.

When multiple executables are disrtibuted together, then separately creating the executables with --exe and --gui-exe can generate multiple copies of collection-based libraries that are used by multiple executables. To share the library code, instead, specify a target directory for library copies using the --collects-dest flag with --exe and --gui-exe, and specify the same directory for each executable (so that the set of libraries used by all executables are pooled together). Finally, when packaging the distribution with --exe-dir, use the ++copy-collects flag to include the copied libraries in the distribution.

5.3  Stand-Alone Executables from Native Code

Creating a stand-alone executable that embeds native code from mzc requires downloading the MzScheme source code and using a C compiler and linker directly.

To build an executable with an embedded MzScheme engine:

For example, under Unix, to create a standalone executable MyApp that is equivalent to

mzscheme -mv -f file1.ss -f file2.ss

unpack the MzScheme source code and perform the following steps:

cd plt/src/mzscheme
./mzmake
./mzmake ee-main
mzc --object --embedded file1.ss
mzc --object --embedded file2.ss
mzc --link-glue --embedded file1.kp file1.o file2.kp file2.o
./mzmake EEAPP=MyApp EEOBJECTS="file1.o file2.o _loader.o" ee-app

To produce an executable that embeds the MrEd engine, the procedure is essentially the same; MrEd's main file is mrmain.cxx instead of main.c. See the compilation notes in the MrEd source code distribution for more information.