Title

Compiling Scheme programs to executables

Author

Marc Nieper-Wißkirchen

Status

This SRFI is currently in final status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi-138@nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.

Abstract

This SRFI describes, for sufficiently POSIX-compatible systems, a portable interface for compiling Scheme programs conforming to the R7RS to binaries that can be directly executed on the host system.

Issues

There are currently no issues.

Rationale

While the R7RS describes portable Scheme programs, it does not describe how to actually store and run such a Scheme program together with its libraries on a host system. This makes it impossible to write portable scripts (including Makefiles) that involve compiling and running Scheme programs.

This situation of Scheme can be compared to the C language. While ISO C does define the syntax and semantics of C programs, it leaves out questions how C programs are compiled and run on the host system. Contrary to Scheme programs, however, there also exists a portable interface for compiling and running C programs (at least on POSIX-conforming systems), namely the description of the c99 utility in the POSIX standard.

It is the purpose of this SRFI to describe an analogous interface for Scheme programs conforming to the R7RS. The description assumes a sufficiently POSIX-compatible system, not because it needs any very POSIX-specific features but because POSIX is a host system interface that has been standardized. Mutatis mutandis, this specification also applies to host systems with a similar file and command line interface as described by POSIX, like Windows.

While this SRFI speaks of compiling Scheme programs, the interface described by this SRFI applies also to Scheme interpreters. The only requirement for the compiler's output is that it is a directly executable program on the host machine. In particular, the resulting binary is allowed to call an interpreter to execute the actual Scheme program.

Specification

Utilities

The following description of the utility described by this SRFI follows in form roughly the description of c99 of the POSIX standard.

Name

compile-r7rs – compile R7RS programs

Synopsis

  compile-r7rs [options...] [pathname]

Description

The compile-r7rs utility is an interface to a compiler for Scheme programs conforming to the R7RS. The program pathname (if present) shall be compiled to produce an executable file. The resulting executable file shall be written to the file specified by the -o option (if present) or to the file file if pathname is of the form file.scm. (Implementations on Windows would choose file.exe instead of file.)

Options

The following options shall be supported:

-D name
Add name to the list of feature identifiers maintained by the Scheme implementation for the purpose of executing the program in the text file pathname.
-A directory
Append directory to the list of directories that are searched in order to locate imported libraries.
-I directory
Prepend directory to the list of directories that are searched in order to locate imported libraries.
-o outfile
Use the pathname outfile, instead of the default a.out, for the executable file produced.

Multiple instances of the -D, -A, and -I options can be specified.

Operands

If exactly one pathname operand of the form file.scm is specified, the application shall behave as specified. If the operand is not of this form, the behaviour is unspecified.

Rationale: This allows an implementation to support additional file types, e.g. top-level programs written for the R6RS, by assigning different extensions to these file types.

If no such operand is given, the application may do nothing or compile the library definitions contained in text files in the directories (and its subdirectories) specified by the -A, and -I options into an implementation-defined format.

Rationale: In implementations supporting precompilation of libraries, libraries are usually precompiled when they are installed as this may need administrator privileges depending on the file system location of the libraries. Thus the above description ensures that compilation of a program can be split into two phases, one happening at library installation time, the other happening when the final executable is build from the program source.

Input Files

The input file shall be a text file containing a R7RS program.

Environment Variables

The following environment variables shall affect the execution of compile-r7rs:
COMPILE_R7RS
If set to a non-empty pathname, which is not the pathname of the running compile-r7rs, the application should forward execution to the program specified by COMPILE_R7RS passing to it the environment and all its arguments.
Rationale: If more than one Scheme system conforming to this SRFI is installed on the host system, this allows for easy selection between the Scheme compilers by setting the COMPILE_R7RS variable accordingly, and running the compile-r7rs provided by either system.

Exit Status

The following exit values shall be returned:

0
Successful compilation.
>0
An error occurred.

Output file

The format of the executable file produced is unspecified (e.g. it may be a shell script). It is unspecified whether the libraries imported from the program are statically linked in the executable file. Thus, if a directory specified by a -A, or -I option is not an absolute pathname, the resulting executable file may not be relocatable in the file system.

Extended Description

Location of Libraries

As the R7RS does not describe a mapping between library names and text files containing library definitions, this SRFI defines such a mapping as follows: First of all, a library name (<library name element> ... <library name element>) is mapped to the (relative) pathname <library name element>/.../<library name element>.sld. If the input file processed by compile-r7rs directly or indirectly imports a library, the application searches an implementation-defined list of directories (which is amended by the -A and -I options) for the pathname corresponding to the library until a valid text file containing a library definition for the imported library is found.

This SRFI does not specify whether this algorithm applies to the standard libraries described by the R7RS.

The algorithm is unspecified if the mapping from library names to pathnames produces invalid pathnames on the host system (e.g. if a library name element contains a null character).

As the mapping from library names to pathnames is not injective (a library name element may contain a slash, for example), implementations are encouraged to allow more than one library definition in a text file that is located by this algorithm.

The application may use compiled versions of the library definitions that are produced by running the utility without a pathname argument instead of the library definitions itself.

Implementation

Notes

In order for a host system to implement this specification, firstly, it has to provide a command named compile-r7rs, and secondly, this command has to fulfill the command-line arguments interface as described above.

For a Scheme system to implement this specification, it is enough to provide the second layer, that is a command, say compile-fantastic-scheme, that conforms to the command-line arguments interface as described above, and to ask the user to create a symlink from compile-fantastic-scheme to a compile-r7rs pathname. (A Scheme system may alternatively provide an option at install time specifying whether the command compile-r7rs should be installed automatically.)

Rationale: If a conforming Scheme implementation was forced to install compile-r7rs automatically, several such Scheme implementations in one host system would likely step on each other's toes. So in the case of more than one conforming Scheme implementation, it is really the system administrator's or the distribution tools' matters to provide compile-r7rs as the command name.

Sample Implementation

There exists no portable implementation (otherwise this SRFI would be moot), so each Scheme implementation supporting this SRFI should ship its own implementation. There are Scheme systems that already implement most of this SRFI: Chibi and Larceny implement the library location algorithm described above. Chibi implements the -D, -A, and -I options. Larceny implements compiling library definitions into an implementation-defined format.

A not very sophisticated sample implementation for Chibi Scheme is provided as a shell script for readers to read and experiment with. (In order for the -D flag to be supported, a post-0.7.3-release version of Chibi is needed.)

Acknowledgements

This SRFI is related to, but not overlapping with SRFI 22. While SRFI 22 describes how Scheme script executables can be written without invoking a compiler, this SRFI does not assume that the compiled file is in any human-readable format. Furthermore, this SRFI assumes an underlying implementation of R7RS and specifies how to locate libraries supplementary to the standard libraries, which is not possible with SRFI 22. Thus, neither SRFI makes the other obsolete.

The specification of c99 by the POSIX standard and the Chibi and Larceny implementations of R7RS were influential while this SRFI was written.

Copyright

Copyright (C) Marc Nieper-Wißkirchen (2016). All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Editor: Arthur A. Gleckler