#lang scribble/doc @(require scribble/manual "common.rkt" (for-label racket/base racket/unit racket/contract launcher/launcher launcher/launcher-sig launcher/launcher-unit compiler/embed racket/gui/base)) @title[#:tag "launcher"]{Installation-Specific Launchers} A @deftech{launcher} is similar to a stand-alone executable, but a launcher is usually smaller and can be created more quickly, because it depends permanently on the local Racket installation and the program's sources. In the case of Unix, a launcher is simply a shell script that runs @exec{racket} or @exec{gracket}. Launchers @emph{cannot} be packaged into a distribution using @exec{raco distribute}. The @exec{raco exe} command creates a launcher when the @Flag{l} or @DFlag{launcher} flag is specified. @defmodule[launcher/launcher] The @racketmodname[launcher/launcher] library provides functions for creating @tech{launchers}. @section{Creating Launchers} @defproc[(make-gracket-launcher [args (listof string?)] [dest path-string?] [aux (listof (cons/c symbol? any/c)) null] [#:tether-mode tether-mode (or/c 'addon 'config #f) 'addon]) void?]{ Creates the launcher @racket[dest], which starts GRacket with the command-line arguments specified as strings in @racket[args]. Extra arguments passed to the launcher at run-time are appended (modulo special Unix/X flag handling, as described below) to this list and passed on to GRacket. If @racket[dest] exists already, as either a file or directory, it is replaced. The optional @racket[aux] argument is an association list for platform-specific options (i.e., it is a list of pairs where the first element of the pair is a key symbol and the second element is the value for that key). See also @racket[build-aux-from-path]. See @racket[create-embedding-executable] for a list that applies to both stand-alone executables and launchers on Windows and Mac OS GRacket; the following additional associations apply to launchers: @itemize[ @item{@racket['independent?] (Windows) --- a boolean; @racket[#t] creates an old-style launcher that works with any Racket or GRacket binary, like @exec{raco.exe}. No other @racket[aux] associations are used for an old-style launcher.} @item{@racket['exe-name] (Mac OS, @racket['script-3m] or @racket['script-cgc] variant) --- provides the base name for a @racket['3m]-/@racket['cgc]-variant launcher, which the script will call ignoring @racket[args]. If this name is not provided, the script will go through the GRacket executable as usual.} @item{@racket['exe-is-gracket] (when @racket['exe-name] is used) --- indicates that @racket['exe-name] refers to the GRacket executable, which is potentially in a @filepath{lib} subdirectory instead of with other GUI applications.} @item{@racket['relative?] (all platforms) --- a boolean, where @racket[#t] means that the generated launcher should find the base GRacket executable through a relative path.} @item{@racket['install-mode] (Windows, Unix) --- either @racket['main], @racket['user], @racket['config-tethered], or @racket['addon-tethered], indicates that the launcher is being installed to an installation-wide place, a user-specific place, an installation-wide place that embeds the configuration path, or a specific place that embeds an addon-directory path; the install mode, in turn, determines whether and where to record @racket['start-menu], @racket['extension-registry], and/or @racket['desktop] information.} @item{@racket['start-menu] (Windows) --- a boolean or real number; @racket[#t] indicates that the launcher should be in the @onscreen{Start} menu by an installer that includes the launcher. A number value is treated like @racket[#t], but also requests that the installer automatically start the application, where the number determines a precedence relative to other launchers that may request starting. A @racket['start-menu] value is used only when @racket['install-mode] is also specified.} @item{@racket['extension-register] (Windows) --- a list of document types for file-extension registrations to be performed by an installer. Each document type is described by a list of six items: @itemlist[ @item{a human-readable string describing the document type, such as @racket["Racket Document"];} @item{a string to use as a key for the document type, such as @racket["Racket.Document"];} @item{a list of strings, where each string is a file extension without the dot, such as @racket['("rkt" "rktl" "rktd")];} @item{a path to a file that supplies the icon, such as @racket["doc.ico"];} @item{a string to represent the command line to handle a document with a matching extension, such as @racket["\"%1\""], where the string will be prefixed with a path to the launcher, and where @litchar{%1} will be replaced with the document path} ] An @racket['extension-registry] value is used only when @racket['install-mode] is also specified.} @item{@racket['desktop] (Unix) --- a string containing the content of a @filepath{.desktop} file for the launcher, where @tt{Exec} and @tt{Icon} entries are added automatically. If an @tt{Exec} entry exists in the string, and if its value starts with a non-empty sequence of alpha-numeric ASCII characters followed by a space, then the space and remainder of the value is appended to the automatically generated value. The @filepath{.desktop} file is written to the directory produced by @racket[(find-apps-dir)] or @racket[(find-user-apps-dir)]. A @racket['desktop] value is used only when @racket['install-mode] is also specified.} @item{@racket['png] (Unix) : An icon file path (suffix @filepath{.png}) to be referenced by a @filepath{.desktop} file (if any); a @racket['png] value takes precedence over a @racket['ico] value, but neither is used unless a @racket['desktop] value is also present.} @item{@racket['ico] (Unix, in addition to more general Windows use) : An icon file path (suffix @filepath{.ico}) that is used in the same way as @racket['png] if no @racket['png] value is available.} ] For Unix/X, the script created by @racket[make-mred-launcher] detects and handles X Windows flags specially when they appear as the initial arguments to the script. Instead of appending these arguments to the end of @racket[args], they are spliced in after any X Windows flags already listed in @racket[args]. The remaining arguments (i.e., all script flags and arguments after the last X Windows flag or argument) are then appended after the spliced @racket[args]. The @racket[tether-mode] argument indicates how much to preserve the current installation's tethering to a configuration directory and/or addon directory based on @racket[(find-addon-tether-console-bin-dir)] and @racket[(find-config-tether-console-bin-dir)]. The @racket['addon] mode allows full tethering, the @racket['config] mode allows only configuration-directory tethering, and the @racket[#f] mode disables tethering. @history[#:changed "6.5.0.2" @elem{Added the @racket[#:tether-mode] argument.}]} @defproc[(make-racket-launcher [args (listof string?)] [dest path-string?] [aux (listof (cons/c symbol? any/c)) null]) void?]{ Like @racket[make-gracket-launcher], but for starting Racket. On Mac OS, the @racket['exe-name] @racket[aux] association is ignored.} @defproc[(make-gracket-program-launcher [file string?] [collection string?] [dest path-string?]) void?]{ Calls @racket[make-gracket-launcher] with arguments that start the GRacket program implemented by @racket[file] in @racket[collection]: @racket[(list "-l-" (string-append collection "/" file))]. The @racket[_aux] argument to @racket[make-gracket-launcher] is generated by stripping the suffix (if any) from @racket[file], adding it to the path of @racket[collection], and passing the result to @racket[build-aux-from-path].} @defproc[(make-racket-program-launcher [file string?] [collection string?] [dest path-string?]) void?]{ Like @racket[make-gracket-program-launcher], but for @racket[make-racket-launcher].} @defproc[(install-gracket-program-launcher [file string?] [collection string?] [name string?]) void?]{ Same as @racketblock[ (make-gracket-program-launcher file collection (gracket-program-launcher-path name)) ]} @defproc[(install-racket-program-launcher [file string?] [collection string?] [name string?]) void?]{ Same as @racketblock[ (make-racket-program-launcher file collection (racket-program-launcher-path name)) ]} @deftogether[( @defproc[(make-mred-launcher [args (listof string?)] [dest path-string?] [aux (listof (cons/c symbol? any/c)) null]) void?] @defproc[(make-mred-program-launcher [file string?] [collection string?] [dest path-string?]) void?] @defproc[(install-mred-program-launcher [file string?] [collection string?] [name string?]) void?] )]{ Backward-compatible version of @racket[make-gracket-launcher], etc., that adds @racket["-I" "scheme/gui/init"] to the start of the command-line arguments.} @deftogether[( @defproc[(make-mzscheme-launcher [args (listof string?)] [dest path-string?] [aux (listof (cons/c symbol? any/c)) null]) void?] @defproc[(make-mzscheme-program-launcher [file string?] [collection string?] [dest path-string?]) void?] @defproc[(install-mzscheme-program-launcher [file string?] [collection string?] [name string?]) void?] )]{ Backward-compatible version of @racket[make-racket-launcher], etc., that adds @racket["-I" "scheme/init"] to the start of the command-line arguments.} @; ---------------------------------------------------------------------- @section{Launcher Path and Platform Conventions} @defproc[(gracket-program-launcher-path [name string?] [#:user? user? any/c #f] [#:tethered? tethered? any/c #f]) path?]{ Returns a pathname for an executable called something like @racket[name] in @itemlist[ @item{the Racket installation --- when @racket[user?] is @racket[#f] and @racket[tethered?] is @racket[#f];} @item{the user's Racket executable directory --- when @racket[user?] is @racket[#t] and @racket[tethered?] is @racket[#f];} @item{an additional executable directory for executables tethered to a particular configuration directory --- when @racket[user?] is @racket[#f] and @racket[tethered?] is @racket[#t]; or} @item{an additional executable directory for executables tethered to a particular addon and configuration directory --- when @racket[user?] is @racket[#t] and @racket[tethered?] is @racket[#t].} ] For Windows, the @filepath{.exe} suffix is automatically appended to @racket[name]. For Unix, @racket[name] is changed to lowercase, whitespace is changed to @litchar{-}, and the path includes the @filepath{bin} subdirectory of the Racket installation. For Mac OS, the @filepath{.app} suffix is appended to @racket[name]. @history[#:changed "6.5.0.2" @elem{Added the @racket[#:tethered?] argument.}]} @defproc[(racket-program-launcher-path [name string?] [#:user? user? any/c #f] [#:tethered? tethered? any/c #f]) path?]{ Returns the same path as @racket[(gracket-program-launcher-path name #:user? user? #:tethered tethered?)]. @history[#:changed "6.5.0.2" @elem{Added the @racket[#:tethered?] argument.}]} @defproc[(gracket-launcher-is-directory?) boolean?]{ Returns @racket[#t] if GRacket launchers for the current platform are directories from the user's perspective. For all currently supported platforms, the result is @racket[#f].} @defproc[(racket-launcher-is-directory?) boolean?]{ Like @racket[gracket-launcher-is-directory?], but for Racket launchers.} @defproc[(gracket-launcher-is-actually-directory?) boolean?]{ Returns @racket[#t] if GRacket launchers for the current platform are implemented as directories from the filesystem's perspective. The result is @racket[#t] for Mac OS, @racket[#f] for all other platforms.} @defproc[(racket-launcher-is-actually-directory?) boolean?]{ Like @racket[gracket-launcher-is-actually-directory?], but for Racket launchers. The result is @racket[#f] for all platforms.} @defproc[(gracket-launcher-add-suffix [path-string? path]) path?]{ Returns a path with a suitable executable suffix added, if it's not present already.} @defproc[(racket-launcher-add-suffix [path-string? path]) path?]{ Like @racket[gracket-launcher-add-suffix], but for Racket launchers.} @defproc[(gracket-launcher-put-file-extension+style+filters) (values (or/c string? false/c) (listof (one-of/c 'packages 'enter-packages)) (listof (list/c string? string?)))]{ Returns three values suitable for use as the @racket[extension], @racket[style], and @racket[filters] arguments to @racket[put-file], respectively. If GRacket launchers for the current platform were directories from the user's perspective, the @racket[style] result is suitable for use with @racket[get-directory], and the @racket[extension] result may be a string indicating a required extension for the directory name. } @defproc[(racket-launcher-put-file-extension+style+filters) (values (or/c string? false/c) (listof (one-of/c 'packages 'enter-packages)) (listof (list/c string? string?)))]{ Like @racket[gracket-launcher-get-file-extension+style+filters], but for Racket launchers.} @deftogether[( @defproc[(mred-program-launcher-path [name string?] [#:user? user? any/c #f] [#:tethered? tethered? any/c #f]) path?] @defproc[(mred-launcher-is-directory?) boolean?] @defproc[(mred-launcher-is-actually-directory?) boolean?] @defproc[(mred-launcher-add-suffix [path-string? path]) path?] @defproc[(mred-launcher-put-file-extension+style+filters) (values (or/c string? false/c) (listof (one-of/c 'packages 'enter-packages)) (listof (list/c string? string?)))] )]{ Backward-compatible aliases for @racket[gracket-program-launcher-path], etc. @history[#:changed "6.5.0.2" @elem{Added the @racket[#:tethered?] argument.}]} @deftogether[( @defproc[(mzscheme-program-launcher-path [name string?] [#:user? user? any/c #f] [#:tethered? tethered? any/c #f]) path?] @defproc[(mzscheme-launcher-is-directory?) boolean?] @defproc[(mzscheme-launcher-is-actually-directory?) boolean?] @defproc[(mzscheme-launcher-add-suffix [path-string? path]) path?] @defproc[(mzscheme-launcher-put-file-extension+style+filters) (values (or/c string? false/c) (listof (one-of/c 'packages 'enter-packages)) (listof (list/c string? string?)))] )]{ Backward-compatible aliases for @racket[racket-program-launcher-path], etc. @history[#:changed "6.5.0.2" @elem{Added the @racket[#:tethered?] argument.}]} @defproc[(installed-executable-path->desktop-path [exec-path path-string?] [user? any/c]) (and/c path? complete-path?)]{ Returns a path for a @filepath{.desktop} file to describe the installed executable at @racket[exec-path]. Only the filename part of @racket[exec-path] is used. The @racket[user?] argument should be true if @racket[exec-path] is installed in a user-specific location (in which case the result path will also be user-specific).} @defproc[(installed-desktop-path->icon-path [desktop-path path-string?] [user? any/c] [suffix bytes?]) (and/c path? complete-path?)]{ Returns a path for an icon file to be referenced by the @filepath{desktop} file at @racket[desktop-path]. Only the filename part of @racket[desktop-path] is used. The @racket[user?] argument should be true if @racket[desktop-path] is installed in a user-specific location (in which case the result path will also be user-specific). The @racket[suffix] argument provides the icon-file suffix, normally either @racket[#"png"] or @racket[#"ico"].} @; ---------------------------------------------------------------------- @section{Launcher Configuration} @defproc[(gracket-launcher-up-to-date? [dest path-string?] [aux (listof (cons/c symbol? any/c))]) boolean?]{ Returns @racket[#t] if the GRacket launcher @racket[dest] does not need to be updated, assuming that @racket[dest] is a launcher and its arguments have not changed.} @defproc[(racket-launcher-up-to-date? [dest path-string?] [aux (listof (cons/c symbol? any/c))]) boolean?]{ Analogous to @racket[gracket-launcher-up-to-date?], but for a Racket launcher.} @defproc[(build-aux-from-path [path path-string?]) (listof (cons/c symbol? any/c))]{ Creates an association list suitable for use with @racket[make-gracket-launcher] or @racket[create-embedding-executable]. It builds associations by adding to @racket[path] suffixes, such as @filepath{.icns}, checking whether such a file exists, and calling @racket[extract-aux-from-path] if so. The results from all recognized suffixes are appended together.} @defproc[(extract-aux-from-path [path path-string?]) (listof (cons/c symbol? any/c))]{ Creates an association list suitable for use with @racket[make-gracket-launcher] or @racket[create-embedding-executable]. It builds associations by recognizing the suffix of @racket[path], where the recognized suffixes are as follows: @itemize[ @item{@filepath{.icns} @'rarr @racket['icns] file for use on Mac OS} @item{@filepath{.ico} @'rarr @racket['ico] file for use on Windows or Unix} @item{@filepath{.png} @'rarr @racket['png] file for use on Unix} @item{@filepath{.lch} @'rarr @racket['independent?] as @racket[#t] (the file content is ignored) for use on Windows} @item{@filepath{.creator} @'rarr @racket['creator] as the initial four characters in the file for use on Mac OS} @item{@filepath{.filetypes} @'rarr @racket['file-types] as @racket[read] content (a single S-expression), and @racket['resource-files] as a list constructed by finding @racket["CFBundleTypeIconFile"] entries in @racket['file-types] (and filtering duplicates); for use on Mac OS} @item{@filepath{.utiexports} @'rarr @racket['uti-exports] as @racket[read] content (a single S-expression); for use on Mac OS} @item{@filepath{.wmclass} @'rarr @racket['wm-class] as the literal content, removing a trailing newline if any; for use on Unix} @item{@filepath{.desktop} @'rarr @racket['desktop] as the literal content; for use on Unix} @item{@filepath{.startmenu} @'rarr @racket['start-menu] as the file content if it @racket[read]s as a real number, @racket[#t] otherwise, for use on Windows} @item{@filepath{.extreg} @'rarr @racket['extension-register] as @racket[read] content (a single S-expression), but with relative (to the @filepath{.extreg} file) paths converted to absolute paths; for use on Windows} ]} @defparam[current-launcher-variant variant symbol?]{ A parameter that indicates a variant of Racket or GRacket to use for launcher creation and for generating launcher names. The default is the result of @racket[(system-type 'gc)]. On Unix and Windows, the possibilities are @racket['cgc] and @racket['3m]. On Mac OS, the @racket['script-3m] and @racket['script-cgc] variants are also available for GRacket launchers.} @defproc[(available-gracket-variants) (listof symbol?)]{ Returns a list of symbols corresponding to available variants of GRacket in the current Racket installation. The list normally includes at least one of @racket['3m] or @racket['cgc]--- whichever is the result of @racket[(system-type 'gc)]---and may include the other, as well as @racket['script-3m] and/or @racket['script-cgc] on Mac OS.} @defproc[(available-racket-variants) (listof symbol?)]{ Returns a list of symbols corresponding to available variants of Racket in the current Racket installation. The list normally includes at least one of @racket['3m] or @racket['cgc]---whichever is the result of @racket[(system-type 'gc)]---and may include the other.} @deftogether[( @defproc[(mred-launcher-up-to-date? [dest path-string?] [aux (listof (cons/c symbol? any/c))]) boolean?] @defproc[(mzscheme-launcher-up-to-date? [dest path-string?] [aux (listof (cons/c symbol? any/c))]) boolean?] @defproc[(available-mred-variants) (listof symbol?)] @defproc[(available-mzscheme-variants) (listof symbol?)] )]{ Backward-compatible aliases for @racket[gracket-launcher-up-to-date?], etc.} @; ---------------------------------------- @section{Launcher Creation Signature} @defmodule[launcher/launcher-sig] @defsignature/splice[launcher^ ()]{ Includes the identifiers provided by @racketmodname[launcher/launcher].} @; ---------------------------------------- @section{Launcher Creation Unit} @defmodule[launcher/launcher-unit] @defthing[launcher@ unit?]{ A unit that imports nothing and exports @racket[launcher^].}