10 KiB
Running and Creating Executables
While developing programs, many Racket programmers use the DrRacket
programming environment. To run a program without the development
environment, use racket
for console-based programs
or gracket
for GUI programs
. This chapter mainly explains how to run racket
and gracket
.
1 Running `racket` and `gracket`
1.1 Interactive Mode
1.2 Module Mode
1.3 Load Mode
2 Scripts
2.1 Unix Scripts
2.2 Windows Batch Files
3 Creating Stand-Alone Executables
1. Running racket
and gracket
The gracket
executable is the same as racket
, but with small
adjustments to behave as a GUI application rather than a console
application. For example, gracket
by default runs in interactive mode
with a GUI window instead of a console prompt. GUI applications can be
run with plain racket
, however.
Depending on command-line arguments, racket
or gracket
runs in
interactive mode, module mode, or load mode.
1.1. Interactive Mode
When racket
is run with no command-line arguments (other than
confguration options, like -j
), then it starts a REPL with a >
prompt:
Welcome to Racket v7.1.0.6.
>
For enhancing your REPL experience, see
xrepl
; for information on GNU Readline support, seereadline
.
To initialize the REPL’s environment, racket
first requires the
racket/init
module, which provides all of racket
, and also installs
pretty-print
for display results. Finally, racket
loads the file
reported by (find-system-path 'init-file)
, if it exists, before
starting the REPL.
If any command-line arguments are provided (other than configuration
options), add -i
or --repl
to re-enable the REPL. For example,
racket -e '(display "hi\n")' -i
displays “hi” on start-up, but still presents a REPL.
If module-requiring flags appear before -i
/--repl
, they cancel the
automatic requiring of racket/init
. This behavior can be used to
initialize the REPL’s environment with a different language. For
example,
racket -l racket/base -i
starts a REPL using a much smaller initial language (that loads much
faster). Beware that most modules do not provide the basic syntax of
Racket, including function-call syntax and require
. For example,
racket -l racket/date -i
produces a REPL that fails for every expression, because racket/date
provides only a few functions, and not the #%top-interaction
and
#%app
bindings that are needed to evaluate top-level function calls in
the REPL.
If a module-requiring flag appears after -i
/--repl
instead of before
it, then the module is required after racket/init
to augment the
initial environment. For example,
racket -i -l racket/date
starts a useful REPL with racket/date
available in addition to the
exports of racket
.
1.2. Module Mode
If a file argument is supplied to racket
before any command-line
switch other than configuration options
, then the file is required
as a module, and unless `-i`/`--repl` is specified
, no REPL is
started. For example,
racket hello.rkt
requires the "hello.rkt"
module and then exits. Any argument after the
file name, flag or otherwise, is preserved as a command-line argument
for use by the required module via current-command-line-arguments
.
If command-line flags are used, then the -u
or --require-script
flag
can be used to explicitly require a file as a module. The -t
or
--require
flag is similar, except that additional command-line flags
are processed by racket
, instead of preserved for the required module.
For example,
racket -t hello.rkt -t goodbye.rkt
requires the "hello.rkt"
module, then requires the "goodbye.rkt"
module, and then exits.
The -l
or --lib
flag is similar to -t
/--require
, but it requires
a module using a lib
module path instead of a file path. For example,
racket -l raco
is the same as running the raco
executable with no arguments, since
the raco
module is the executable’s main module.
Note that if you wanted to pass command-line flags to raco
above, you
would need to protect the flags with a --
, so that racket
doesn’t
try to parse them itself:
racket -l raco -- --help
1.3. Load Mode
The -f
or --load
flag supports load
ing top-level expressions in a
file directly, as opposed to expressions within a module file. This
evaluation is like starting a REPL and typing the expressions directly,
except that the results are not printed. For example,
racket -f hi.rkts
load
s "hi.rkts"
and exits. Note that load mode is generally a bad
idea, for the reasons explained in [missing]; using module mode is
typically better.
The -e
or --eval
flag accepts an expression to evaluate directly.
Unlike file loading, the result of the expression is printed, as in a
REPL. For example,
racket -e '(current-seconds)'
prints the number of seconds since January 1, 1970.
For file loading and expression evaluation, the top-level environment is
created in the same way for interactive mode: racket/init
is required
unless another module is specified first. For example,
racket -l racket/base -e '(current-seconds)'
likely runs faster, because it initializes the environment for
evaluation using the smaller racket/base
language, instead of
racket/init
.
2. Scripts
Racket files can be turned into executable scripts on Unix and Mac OS. On Windows, a compatibility layer like Cygwin support the same kind of scripts, or scripts can be implemented as batch files.
2.1. Unix Scripts
In a Unix environment including Linux and Mac OS
, a Racket file can
be turned into an executable script using the shell’s #!
convention.
The first two characters of the file must be #!
; the next character
must be either a space or /
, and the remainder of the first line must
be a command to execute the script. For some platforms, the total length
of the first line is restricted to 32 characters, and sometimes the
space is required.
Use
#lang
racket/base
instead of#lang
racket
to produce scripts with a faster startup time.
The simplest script format uses an absolute path to a racket
executable followed by a module declaration. For example, if racket
is
installed in "/usr/local/bin"
, then a file containing the following
text acts as a “hello world” script:
#! /usr/local/bin/racket
#lang racket/base
"Hello, world!"
In particular, if the above is put into a file "hello"
and the file is
made executable e.g., with `chmod a+x hello`
, then typing ./hello
at the shell prompt produces the output "Hello, world!"
.
The above script works because the operating system automatically puts
the path to the script as the argument to the program started by the
#!
line, and because racket
treats a single non-flag argument as a
file containing a module to run.
Instead of specifying a complete path to the racket
executable, a
popular alternative is to require that racket
is in the user’s command
path, and then “trampoline” using /usr/bin/env
:
#! /usr/bin/env racket
#lang racket/base
"Hello, world!"
In either case, command-line arguments to a script are available via
current-command-line-arguments
:
#! /usr/bin/env racket
#lang racket/base
(printf "Given arguments: ~s\n"
(current-command-line-arguments))
If the name of the script is needed, it is available via
(find-system-path 'run-file)
, instead of via
(current-command-line-arguments)
.
Usually, the best way to handle command-line arguments is to parse them
using the command-line
form provided by racket
. The command-line
form extracts command-line arguments from
(current-command-line-arguments)
by default:
#! /usr/bin/env racket
#lang racket
(define verbose? (make-parameter #f))
(define greeting
(command-line
#:once-each
[("-v") "Verbose mode" (verbose? #t)]
#:args
(str) str))
(printf "~a~a\n"
greeting
(if (verbose?) " to you, too!" ""))
Try running the above script with the --help
flag to see what
command-line arguments are allowed by the script.
An even more general trampoline uses /bin/sh
plus some lines that are
comments in one language and expressions in the other. This trampoline
is more complicated, but it provides more control over command-line
arguments to racket
:
#! /bin/sh
#|
exec racket -e '(printf "Running...\n")' -u "$0" ${1+"$@"}
|#
#lang racket/base
(printf "The above line of output had been produced via\n")
(printf "a use of the
-e' flag.\n")
(printf "Given arguments: ~s\n"
(current-command-line-arguments))`
Note that #!
starts a line comment in Racket, and #|
...|#
forms a
block comment. Meanwhile, #
also starts a shell-script comment, while
exec racket
aborts the shell script to start racket
. That way, the
script file turns out to be valid input to both /bin/sh
and racket
.
2.2. Windows Batch Files
A similar trick can be used to write Racket code in Windows .bat
batch
files:
; @echo off
; Racket.exe "%~f0" %*
; exit /b
#lang racket/base
"Hello, world!"
3. Creating Stand-Alone Executables
For information on creating and distributing executables, see
missing