To compile an individual file with mzc, provide the file name as
the command line argument to mzc. To compile to byte code, use the
-z or --zo flag; to compile to native code, use
the -e or --extension flag. If no compilation
mode flag is specified, --extension is assumed.
The input file must have a file extension that designates it as a
Scheme file, either .ss or .scm. The output
file will have the same base name and same directory (by default) as
the input file, but with an extension appropriate to the type of the
output file (either .zo, .dll, or .so).
Example:
mzc --extension file.ss
Under Windows, the above command reads file.ss from the current
directory and produces file.dll in the current directory.
Multiple Scheme files can be specified for compilation at once. A
separate compiled file is produced for each Scheme file. By default,
each compiled file is placed in the directory containing the
corresponding input file. When multiple files are compiled at once,
macros defined in a file are visible in the files that are compiled
afterwards.
In terms of both optimization and proper loading of syntax
definitions, mzc works best with programs that are encapulated
within per-file module expressions. Using a single
module expression in a file eliminates the code's dependence
on the top-level environment. Consequently, all dependencies of the
code on loadable syntax extensions are evident to the compiler.
When compiling a module that requires another module (that is
not built into MzScheme), mzc loads the required module, but does
not invoke it. Instead, mzc uses the loaded module only for its
syntax exports, if any (which means that mzc executes the
transformer code in the module, but not any of its normal code).
Top-level define-syntax(es), module,
require, require-for-syntax, and begin
expressions are handled specially by mzc: the compile-time portion
of the expression is evaluated, because it might affects later
expressions.2 For example, when compiling the file
containing
(require (lib "etc.ss"))
(definef (opt-lambda (a [b7]) (+ab)))
the opt-lambda syntax from the "etc.ss" library must be
bound in the compilation namespace at compile time. Thus, the
require expression is both compiled (to appear in the output
code) and evaluated (for further computation).
Many definition forms expand to define-syntax. For example,
define-signature expands to a define-syntax
definition. mzc detects define-syntax and other expressions
after expansion, so top-level define-signature expressions
affect the compilation of later expressions, as a programmer would
expect.
In contrast, a load or eval expression in a source
file is compiled -- but not evaluated! -- as the source file is
compiled. Even if the load expression loads syntax or
signature definitions, these will not be loaded as the file is
compiled. The same is true of application expressions that affect the
reader, such as (read-case-sensitive#t).
mzc's -p or --prefix flag takes a file and
loads it before compiling the source files specified on the command
line. In general, a better solution is to put all compiled code into
module expressions, as explained in section 3.1.
Note that MzScheme provides no eval-when form for
controlling the evaluation of compiled code, because module
provides a simpler and more consistent interface for separating
compile-time and run-time code.
When MzScheme's load/use-compiled, load-relative, or
require is used to load a file, MzScheme automatically detects
an alternate byte-code and/or native-code file that resides near the
requested file. Byte-code files are found in a compiled
subdirectory in the directory of the requested file. Native-code
files are found in (build-pathdir"compiled""native"
(system-library-subpath)) where dir is the directory of the
requested file. A byte-code or native-code file is used in place of
the requested file only if its modification date is later than the
requested file, or if the requested file does not exist. If both
byte-code and native-code files can be loaded, the native-code file
is loaded.
Under Linux, the above command compiles file.ss in the current
directory and produces compiled/native/i386-linux/file.so.
Evaluating (load/use-compiled"file.ss") in MzScheme will then
load compiled/native/i386-linux/file.so instead of
file.ss. If file.ss is changed without recreating
file.so, then load/use-compiled loads file.ss,
because file.so is out-of-date.
When the -o or --object flag is provided to
mzc, .kp and .o/.obj files are produced
instead of a loadable library. The .o/.obj files
contain the native code for a single source file. The .kp
files contain information used for global optimizations.
Multiple .kp and .o/.obj files are linked into a
single library using mzc with the -l or
--link-extension flag. All of the .kp and
.o/.obj files to be linked together are provided on the
command line to mzc. The output library is always named
_loader.so or _loader.dll.
Under Unix, the above commands produce a _loader.so library
that encapsulates both file1.ss and file2.ss.
Loading _loader into MzScheme is not quite the same as loading
all of the Source files that are encapsulated by _loader. The
return value from (load-extension"_loader.so") is a
procedure that takes a symbol or #t. If a symbol is provided
and it is the same as the base name of a source file (i.e., the name
without a path or file extension) encapsulated by _loader,
then a thunk is returned, along with a symbol (or #f)
indicating a module name declared by the file. Applying the thunk has
the same effect as loading the corresponding source file. If a symbol
is not recognized by the _loader procedure, #f is
returned instead of a thunk. If #t is provided, a thunk is
returned that ``loads'' all of the files (using the order of the
.o/.obj files provided to mzc) and returns the
result from loading the last one.
The _loader procedure can be called any number of times to
obtain thunks, and each thunk can be applied any number of times
(where each application has the same effect as loading the source
file again). Evaluating (load-extension"_loader.so")
multiple times returns an equivalent loader procedure each time.
Given the _loader.so constructed by the example commands
above, the following Scheme expressions have the same effect as
loading file1.ss and file2.ss:
The special _loader convention is recognized by MzScheme's
load/use-compiled, load-relative, and
require. MzScheme automatically detects _loader.so or
_loader.dll in the same directory as individual native-code
files (see section 3.3). If both an individual native-code
file and a _loader are available, the _loader file is
used.
2 The -m or --module flag turns off
this special handling.