racket/pkgs/racket-doc/scribblings/raco/exe.scrbl
Matthew Flatt e01a21db0c raco exe: add --embed-dlls for Windows
Creating an executable with embedded DLLs means that the executable
can be truly stand-alone, instead of needing to be kept with its
DLLs in a relative subdirectory.

DLL embedding works by bypassing the OS's LoadLibrary and
GetProcAddress functions, and instead maps the DLL into memory
and performs relocations explicitly. Joachim Bauch's MemoryModule
(Mozilla license) implements those steps.
2018-03-25 16:35:42 -06:00

204 lines
9.4 KiB
Racket

#lang scribble/doc
@(require scribble/manual
scribble/bnf
"common.rkt"
(for-label racket/base
racket/runtime-path
compiler/embed
launcher/launcher))
@(define (gtech s) (tech #:doc '(lib "scribblings/guide/guide.scrbl") s))
@title[#:tag "exe"]{@exec{raco exe}: Creating Stand-Alone Executables}
@margin-note{To achieve a faster startup time, instead of trying
@exec{raco exe}, use a smaller base language---such as
@racketmodfont{#lang} @racketmodname[racket/base] instead of
@racketmodfont{#lang} @racketmodname[racket]. Also, ensure that
bytecode files are compiled by using @seclink["make"]{@exec{raco make}}.}
Compiled code produced by @exec{raco make} relies on Racket
executables to provide run-time support to the compiled code. However,
@exec{raco exe} can package code together with its run-time support to
form an executable, and @exec{raco distribute} can package the
executable into a distribution that works on other machines. Running
an executable produced by @exec{raco exe} will not improve performance
over @exec{raco make}.
The @exec{raco exe} command embeds a module, from source or byte
code, into a copy of the @exec{racket} executable. (On Unix, the
embedding executable is actually a copy of a wrapper executable.) The
created executable invokes the embedded module on startup. The
@DFlag{gui} flag causes the program to be embedded in a copy of the
@exec{gracket} executable. If the embedded module refers to other
modules via @racket[require], then the other modules are also included
in the embedding executable.
For example, the command
@commandline{raco exe --gui hello.rkt}
produces either @filepath{hello.exe} (Windows), @filepath{hello.app}
(Mac OS), or @filepath{hello} (Unix), which runs the same as running
the @filepath{hello.rkt} module in @exec{gracket}.
Library modules or other files that are referenced
dynamically---through @racket[eval], @racket[load], or
@racket[dynamic-require]---are not automatically embedded into the
created executable. Such modules can be explicitly included using the
@DPFlag{lib} flag to @exec{raco exe}. Alternately, use
@racket[define-runtime-path] 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
@secref["exe-dist"]). Finally, a submodule is included if its
enclosing module is included and the submodule contains a
sub-submodule named @racketidfont{declare-preserve-for-embedding}
(where the implementation of the sub-submodule is ignored).
Modules that are implemented directly by extensions---i.e., extensions
that are automatically loaded from @racket[(build-path "compiled"
"native" (system-library-subpath))] to satisfy a
@racket[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 @exec{raco exe} command works only with module-based programs. The
@racketmodname[compiler/embed] library provides a more general
interface to the embedding mechanism.
A stand-alone executable is ``stand-alone'' in the sense that you can
run it without starting @exec{racket}, @exec{gracket}, or
DrRacket. However, the executable may depend on Racket shared libraries
and possibly other run-time files declared via
@racket[define-runtime-path]. The executable can be packaged with
support libraries to create a distribution using @exec{raco
distribute}, as described in @secref["exe-dist"].
The @exec{raco exe} command accepts the following command-line flags:
@itemlist[
@item{@Flag{o} @nonterm{file} --- create the executable as
@nonterm{file}, adding a suffix to @nonterm{file} as appropriate
for the platform and executable type. On Mac OS in @DFlag{gui}
mode, @nonterm{file} is actually a bundle directory, but it appears
as a file within Finder.}
@item{@DFlag{gui} --- create a graphical executable based on
@exec{gracket} instead of @exec{racket}.}
@item{@Flag{l} or @DFlag{launcher} --- create a @tech{launcher} (see
@secref["launcher"]), instead of a stand-alone executable. Flags
such as @DFlag{config-path}, @DFlag{collects-path}, and @DFlag{lib}
have no effect on launchers. Beware that the default command-line
flags to build into the launcher prevent access to packages that
are installed in user scope; use @exec{--exf -U} to enable access
to user-scope packages from the launcher.}
@item{@DFlag{embed-dlls} --- On Windows, for a stand-alone executable,
copies any needed DLLs into the executable. Embedding DLLs makes
the resulting executable truly stand-alone if it does not depend on
other external files. Not all DLLs work with embedding, and
limitations are mostly related to thread-local storage and
resources, but all DLLs within the main Racket distribution work
with @DFlag{embed-dlls}.}
@item{@DFlag{config-path} @nonterm{path} --- set @nonterm{path}
within the executable as the path to the @tech{configuration
directory}; if the path is relative, it will be treated as relative
to the executable. The default path is @filepath{etc}, with the
expectation that no such directory will exist at run time.}
@item{@DFlag{collects-path} @nonterm{path} --- set @nonterm{path}
within the executable as the path to the @tech{main collection
directory}; if the path is relative, it will be treated as relative
to the executable. The default is to have no path, which means that
the @racket[current-library-collection-paths] and
@racket[current-library-collection-links] parameters are
initialized as @racket[null] when the executable starts. Beware that
various other directories are located relative to the @tech{main
collection directory} by default (see @secref["config-file"]), so
that installing @nonterm{path} may allow other directories to be
found---intentional or not.}
@item{@DFlag{collects-dest} @nonterm{path} --- write modules to be
included with the executable into @nonterm{path}
(relative to the current directory), instead of embedded within the
executable. The @DFlag{collects-dest} flag normally makes sense
only in combination with @DFlag{collects-path}. This mode currently
does not prune unreferenced submodules (and it pulls along any
dependencies of submodules).}
@item{@DFlag{ico} @nonterm{.ico-path} --- on Windows, set the icons
for the generated executable to ones extracted from
@nonterm{.ico-path}; see @racket[create-embedding-executable]'s
use of the @racket['ico] auxiliary association for more information
about expected icon sizes and transformations.}
@item{@DFlag{icns} @nonterm{.icns-path} --- on Mac OS, set the icons
for the generated executable to be the content of
@nonterm{.icns-path}.}
@item{@DFlag{orig-exe} --- generate an executable that refers to
the original @exec{racket} or @exec{gracket} executable,
instead of making a copy. This flag is rarely useful, because the
part of the executable that is copied is normally small, and
@exec{raco distribute} does not work with executables that are
created with @DFlag{orig-exe}.}
@item{@DFlag{3m} --- generate an executable based on the @gtech{3m}
variant of Racket, which is the default unless running a @exec{raco
exe} that is based on the @gtech{CGC} variant.}
@item{@DFlag{cgc} --- generate an executable based on the @gtech{CGC}
variant of Racket, which is the default only when running a
@exec{raco exe} that is based on the @gtech{CGC} variant.}
@item{@DFlag{cs} --- generate an executable based on the @gtech{cs}
variant of Racket, which is the default unless running a @exec{raco
exe} that is based on the @gtech{CS} variant.}
@item{@DPFlag{aux} @nonterm{file} --- attach information to the
executable based on @nonterm{file}'s suffix; see
@racket[extract-aux-from-path] for a list of recognized suffixes
and meanings, and see @racket[create-embedding-executable]'s use of
auxiliary association for more specific information about how each
kind of file is used.}
@item{@DPFlag{lib} @nonterm{module-path} --- include @nonterm{module-path}
in the executable, even if it is not referenced by the main program,
so that it is available via @racket[dynamic-require].}
@item{@DPFlag{exf} @nonterm{flag} --- provide the @nonterm{flag}
command-line argument on startup to the embedded @exec{racket} or
@exec{gracket}.}
@item{@DFlag{exf} @nonterm{flag} --- remove @nonterm{flag} from the
command-line arguments to be provided on startup to the embedded
@exec{racket} or @exec{gracket}.}
@item{@DFlag{exf-clear} --- remove all command-line arguments to be
provided on startup to the embedded @exec{racket} or
@exec{gracket}.}
@item{@DFlag{exf-show} --- show (without changing) the command-line
arguments to be provided on startup to the embedded
@exec{racket} or @exec{gracket}.}
@item{@Flag{v} --- report progress verbosely.}
@item{@DFlag{vv} --- report progress more verbosely than @Flag{v}.}
]
@history[#:changed "6.3.0.11" @elem{Added support for
@racketidfont{declare-preserve-for-embedding}.}
#:changed "6.90.0.23" @elem{Added @DFlag{embed-dlls}.}]
@; ----------------------------------------------------------------------
@include-section["exe-api.scrbl"]
@include-section["launcher.scrbl"]
@include-section["exe-dylib-path.scrbl"]