www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

distro-build.scrbl (30485B)


      1 #lang scribble/manual
      2 @(require scribble/bnf
      3           (for-label distro-build/config
      4                      distro-build/readme))
      5 
      6 @title{Building Distributions of Racket}
      7 
      8 The @filepath{distro-build} collection provides tools for creating a
      9 Racket distribution---like the ones available at
     10 @url{http://download.racket-lang.org}, but perhaps for different
     11 versions or with different packages pre-installed.
     12 
     13 The distribution-building tools are meant to be driven by a makefile
     14 in the main Racket source repository, which is currently
     15 @url{https://github.com/plt/racket}. See @filepath{INSTALL.txt} there
     16 for general build information.
     17 
     18 @; ----------------------------------------
     19 
     20 @section{Site Configuration Modules}
     21 
     22 A build farm is normally run via the @tt{installers}, @tt{site}, or
     23 @tt{snapshot-site} target of the Racket repository's top-level
     24 makefile. The latter two targets chain to the @tt{installers} target,
     25 which expects a @tt{CONFIG=...} argument to specify a configuration
     26 module file (or uses @filepath{build/site.rkt} as the default).
     27 
     28 A site configuration module starts @racket[@#,hash-lang[]
     29 @#,racketmodname[distro-build/config]] and uses keywords to specify
     30 various options for the configuration. This format is described is
     31 detail in @secref["distro-build-language"]. For now, it's enough to
     32 know that there are various options, each of which is associated with
     33 a keyword.
     34 
     35 The machine where @exec{make installers} is run is the @deftech{server
     36 machine}. The server machine first prepares packages for installation
     37 on @deftech{client machines}. The site configuration's top-level entry
     38 is consulted for a @racket[#:pkgs] and/or @racket[#:doc-search]
     39 option, which overrides any @tt{PKGS} and/or @tt{DOC_SEARCH}
     40 configuration from the makefile.
     41 
     42 The site configuration file otherwise describes and configures
     43 client machines hierarchically, where configuration options
     44 propagate down the hierarchy when they are not overridden more
     45 locally.
     46 
     47 Each client is normally built by running commands via @exec{ssh},
     48 where the client's host configured with @racket[#:host] (with and
     49 optional @racket[#:port] and/or @racket[#:user]) indicate the
     50 @exec{ssh} target. Each client machine must be set up with a
     51 public-key authentication, because a direct @exec{ssh} is expected to
     52 work without a password prompt. An exception is when the host is
     53 @racket["localhost"] and user is @racket[#f], in which case a shell is
     54 used directly instead of @exec{ssh}. When @exec{ssh} is used, @Flag{R}
     55 is also used to create a tunnel back to the server, and the client by
     56 default uses that tunnel for all communication, so the server by
     57 default accepts only connections via @racket["localhost"].
     58 
     59 On the client machine, all work is performed at a specified directory
     60 as specified by @racket[#:dir]. The directory defaults to
     61 @filepath{build/plt} (Unix or Mac OS X) or @filepath{build\plt}
     62 (Windows), except when the host is @racket["localhost"] and the client
     63 is @racket[#f], in which case the current directory (i.e., the
     64 server's directory) is used.
     65 
     66 Normally, the client directory is a Git clone:
     67 
     68 @itemlist[
     69 
     70   @item{If the directory exists already on a client machine (and the
     71     machine is not configured for ``clean'' mode), then if the
     72     directory contains a @filepath{.git} subdirectory, it is assumed
     73     to be a git clone and updated with @exec{git pull}. The @exec{git
     74     pull} operation can be disabled by specifying @racket[#:pull?] as
     75     @racket[#f], and it defaults to @racket[#f] in the case that
     76     @racket[#:dir] is not specified, the host is @racket["localhost"],
     77     and the user is @racket[#f].}
     78 
     79   @item{If the directory does not exist, a Git repository is cloned.
     80     The repository can be specified with @racket[#:repo]. By default,
     81     the server is used as the source Git repository (so that the
     82     server and client are in sync), which means that the server's
     83     directory must be a Git clone.}
     84 
     85 ]
     86 
     87 Note that neither @exec{ssh} nor @exec{git} turn out to be needed when
     88 the host is @racket["localhost"], the user is @racket[#f], and the
     89 directory is not specified (which corresponds to the defaults in all
     90 cases).
     91 
     92 If a build fails for a machine, building continues on other machines.
     93 Success for a given machine means that its installer ends up in
     94 @filepath{build/installers} (and failure for a machine means no
     95 installer) as recorded in the @filepath{table.rktd} file.
     96 
     97 To use the @tt{site} makefile target, the configuration file must at
     98 least provide a @racket[#:dist-base-url] value, which is a URL at which the
     99 site will be made available. To use the @tt{snapshot-site} makefile
    100 target, then @racket[#:site-dest] will need to be specified, normally as a
    101 path that ends with the value produced by @racket[(current-stamp)].
    102 
    103 Hint: When developing a configuration file, use an empty set of
    104 packages to a configuration that works as quickly as possible. Then,
    105 change the list of packages to the ones that you actually want in the
    106 installers.
    107 
    108 
    109 @; ----------------------------------------
    110 
    111 @section{Machine Requirements}
    112 
    113 Each Unix or Mac OS X @tech{client machine} needs the following available:
    114 
    115 @itemlist[
    116 
    117   @item{SSH server with public-key authentication (except @racket["localhost"])}
    118   
    119   @item{@exec{git} (unless the working directory is ready)}
    120 
    121   @item{@exec{gcc}, @exec{make}, etc.}
    122 
    123   @item{when creating a Windows installer (via cross-compilation),
    124         Nullsoft Scriptable Install System (NSIS) version 2.x with
    125         @exec{makensis} in @envvar{PATH}}
    126 
    127 ]
    128 
    129 Each Windows @tech{client machine} needs the following:
    130 
    131 @itemlist[
    132 
    133   @item{SSH server with public-key authentication, providing either a
    134     Windows command line (like freeSSHd) or bash with access to
    135     @exec{cmd.exe} (like Cygwin's @exec{opensshd})}
    136     
    137   @item{@exec{git} (unless the working directory is ready)}
    138   
    139   @item{Microsoft Visual Studio (version at least 9.0 and no more than 12.0), installed
    140     in the default folder:
    141      @filepath{C:\Program Files\Microsoft Visual Studio @nonterm{vers}}
    142     or
    143      @filepath{C:\Program Files (x86)\Microsoft Visual Studio @nonterm{vers}}}
    144      
    145   @item{Nullsoft Scriptable Install System (NSIS) version 2.x, installed
    146     in the default folder:
    147      @filepath{C:\Program Files\NSIS\makensis.exe}
    148     or
    149      @filepath{C:\Program Files (x86)\NSIS\makensis.exe}
    150     or installed so that @exec{makensis} in @envvar{PATH}}
    151 
    152 ]
    153 
    154 Currently, Windows and Unix variants can be cross-compiled using a
    155 same-versioned native Racket installation on a client machine that
    156 runs Unix or Mac OS X.
    157 
    158 @; ----------------------------------------
    159 
    160 @section[#:tag "distro-build-language"]{Site Configuration Language}
    161 
    162 A site configuration module is normally written in the
    163 @racketmodname[distro-build/config] language. The configuration
    164 describes individual machines, and groups them with @racket[parallel]
    165 or @racket[sequential] to indicate whether the machine's builds should
    166 run sequentially or in parallel. Options specified at
    167 @racket[parallel] or @racket[sequential] are propagated to each
    168 machine in the group.
    169 
    170 @defmodulelang[distro-build/config]
    171 
    172 The @racketmodname[distro-build/config] language is like
    173 @racketmodname[racket/base] except that the module body must have
    174 exactly one expression (plus any number of definitions, etc.) that
    175 produces a site-configuration value. The value is exported as
    176 @racket[site-config] from the module. Any module can act as a
    177 site-configuration module a long as it exports @racket[site-config] as
    178 a site-configuration value.
    179 
    180 Site-configuration values are created with @racket[sequential],
    181 @racket[parallel], and @racket[machine]:
    182 
    183 @deftogether[(
    184 @defproc[(machine ...) site-config?]
    185 @defproc[(parallel ... [config site-config] ...) site-config?]
    186 @defproc[(sequential ... [config site-config] ...) site-config?]
    187 )]{
    188 
    189 Produces a site configuration based on the given keyword-based
    190 options as described below. The @racket[sequential] function
    191 produces a site configuration that runs each @racket[config]
    192 sequentially. The @racket[parallel] function
    193 produces a site configuration that runs each @racket[config]
    194 in parallel.
    195 
    196 Site-configuration keyword arguments (where @racket[_string*] means no
    197 spaces, etc.):
    198 
    199 @itemlist[
    200 
    201   @item{@racket[#:host _string*] --- defaults to @racket["localhost"]}
    202 
    203   @item{@racket[#:name _string] --- defaults to @racket[#:host]'s
    204     value; this string is recorded as a description of the installer
    205     and can be used in a generated table of installer links; see also
    206     @secref["name-format"]}
    207 
    208   @item{@racket[#:port _integer] --- SSH port for the client;
    209     defaults to @racket[22]}
    210 
    211   @item{@racket[#:user _string*-or-false] --- SSH user for the client;
    212     defaults to @racket[#f], which means the current user}
    213 
    214   @item{@racket[#:dir _path-string] --- defaults to
    215     @racket["build/plt"] or @racket["build\\plt"], or to the current
    216     directory if the host is @racket["localhost"] and the user is
    217     @racket[#f]}
    218 
    219   @item{@racket[#:env (list (list _string* _string) ...)] ---
    220     environment-variable settings to prefix all client-machine
    221     interactions for a Unix or Mac OS X client; for example
    222     @racket['(("PATH" "/usr/local/bin:/usr/bin"))] configures the
    223     client machine's @envvar{PATH} enviornment variable to have
    224     only @filepath{/usr/local/bin} and @filepath{/usr/bin}}
    225 
    226   @item{@racket[#:server _string*] --- the address of the server as
    227     accessed by the client; when SSH remote tunneling works, then
    228     @racket["localhost"] should work to reach the server; defaults to
    229     the @tt{SERVER} makefile variable, which in turn defaults to
    230     @racket["localhost"]}
    231 
    232   @item{@racket[#:server-port _integer] --- the port of the server as
    233     accessed by the client, and also the port started on clients to
    234     tunnel back to the server; defaults to the @tt{SERVER_PORT}
    235     makefile variable, which in turn defaults to @racket[9440]}
    236 
    237   @item{@racket[#:server-hosts (list _string* ...)] --- addresses that
    238     determine the interfaces on which the server listens; an empty
    239     list means all of the server's interfaces, while @racket[(list
    240     "localhost")] listens only on the loopback device; defaults to the
    241     @tt{SERVER_HOSTS} makefile variable split on commas, which in turn
    242     defaults to @racket[(list "localhost")]}
    243 
    244   @item{@racket[#:repo _string] --- the git repository for Racket;
    245     defaults to
    246     @filepath{http://@nonterm{server}:@nonterm{server-port}/.git}}
    247 
    248   @item{@racket[#:pkgs (list _string* ...)] --- packages to install;
    249     defaults to the @tt{PKGS} makefile variable}
    250 
    251   @item{@racket[#:dist-base-url _string] --- a URL that is used to
    252     construct a default for @racket[#:doc-search] and
    253     @racket[#:dist-catalogs], where the constructed values are
    254     consistent with converting a build server's content into a
    255     download site; since URLs are constructed via relative paths, this
    256     URL normally should end with a slash}
    257 
    258   @item{@racket[#:doc-search _string] --- URL to install as the
    259     configuration for remote documentation searches in generated
    260     installers; @racket[""] is replaced with the PLT default; defaults
    261     to the @racket[#:dist-base-url] setting (if present) extended with
    262     @racket["doc/local-redirect/index.html"] or the @tt{DOC_SEARCH}
    263     makefile variable}
    264 
    265   @item{@racket[#:install-name _string] --- string used as the name of
    266     the installation for package operations in the @tt{user} package
    267     scope, where @racket[""] keeps the name as the Racket version; the
    268     default is @racket["snapshot"] if the value of @racket[#:release?]
    269     is @racket[#f], @racket[""] otherwise}
    270 
    271   @item{@racket[#:build-stamp _string] --- a string representing a
    272      build stamp, recorded in installers; the default is from the
    273      @tt{BUILD_STAMP} makefile variable or generated if the value of
    274      @racket[#:release?] is @racket[#f], @racket[""] otherwise}
    275 
    276   @item{@racket[#:dist-name _string] --- the distribution name;
    277     defaults to the @tt{DIST_NAME} makefile variable}
    278 
    279   @item{@racket[#:dist-base _string*] --- the distribution's
    280     installater name prefix; defaults to the @tt{DIST_BASE} makefile
    281     variable}
    282 
    283   @item{@racket[#:dist-dir _string*] --- the distribution's
    284     installation directory; defaults to the @tt{DIST_DIR} makefile
    285     variable}
    286 
    287   @item{@racket[#:dist-suffix _string*] --- a suffix for the
    288     installer's name, usually used for an operating-system variant;
    289     defaults to the @tt{DIST_SUFFIX} makefile variable}
    290 
    291   @item{@racket[#:dist-catalogs (list _string ...)] --- catalog URLs
    292     to install as the initial catalog configuration in generated
    293     installed, where @racket[""] is replaced with the PLT default
    294     catalogs; defaults to the @racket[#:dist-base-url] value (if
    295     present) extended with @racket["catalogs"] in a list followed by
    296     @racket[""]}
    297 
    298   @item{@racket[#:readme _string-or-procedure] --- the content of a
    299     @filepath{README} file to include in installers, or a function
    300     that takes a hash table for a configuration and returns a string;
    301     the default is the @racket[make-readme] function from
    302     @racketmodname[distro-build/readme]}
    303 
    304   @item{@racket[#:max-vm _real] --- maximum number of VMs allowed to
    305     run with this machine, counting the machine; defaults to
    306     @racket[1]}
    307 
    308   @item{@racket[#:vbox _string] --- Virtual Box machine name (as
    309     shown, for example, in the Virtual Box GUI); if provided, the
    310     virtual machine is started and stopped on the server as needed}
    311 
    312   @item{@racket[#:platform _symbol] --- @racket['unix],
    313     @racket['macosx], @racket['windows], or @racket['windows/bash]
    314     (which means @racket['windows] though an SSH server providing
    315     @exec{bash}, such as Cygwin's); the @racket[_symbol] names
    316     the client machine's system, not the target for cross-compilation;
    317     defaults to @racket[(system-type)]}
    318 
    319   @item{@racket[#:configure (list _string ...)] --- arguments to
    320     @exec{configure}}
    321 
    322   @item{@racket[#:cross-target _string*] --- specifies a target for
    323     cross-compilation, which adds @DFlag{host}@tt{=}@racket[_string*]
    324     to the start of the list of @exec{configure} arguments; in
    325     addition, if no @racket[#:racket] value is provided, a native
    326     @exec{racket} executable for the client machine is created (by
    327     using @exec{configure} with no arguments) and used for
    328     cross-compilation in the same way as a @racket[#:racket] value}
    329 
    330   @item{@racket[#:racket _string-or-false] --- an absolute path to a
    331     native Racket executable to use for compilation, especially
    332     cross-compilation; if the value is @racket[#f], then the Racket
    333     executable generated for the client machine is used to prepare the
    334     installer, or a client-native executable is generated
    335     automatically if @racket[#:cross-target] is specified; a
    336     non-@racket[#f] value for @racket[#:racket] is propagated to
    337     @racket[#:configure] via @DFlag{enable-racket}}
    338 
    339   @item{@racket[#:target-platform _symbol] --- @racket['unix],
    340     @racket['macosx], or @racket['windows], or @racket[#f], indicating
    341     the target platform's type (which is different from the client
    342     system type in the case of cross-compilation); defaults to
    343     @racket[#f], which means that the target platform should be
    344     inferred from arguments such as @racket[#:cross-target]}
    345 
    346   @item{@racket[#:bits _integer] --- @racket[32] or @racket[64];
    347     affects Visual Studio mode}
    348 
    349   @item{@racket[#:vc _string*] --- provided to
    350     @filepath{vcvarsall.bat} to select the Visual Studio build mode;
    351     the default is @racket["x86"] or @racket["x86_amd64"], depending
    352     on the value of @racket[#:bits]}
    353 
    354   @item{@racket[#:sign-identity _string] --- provides an identity to
    355     be passed to @exec{codesign} for code signing on Mac OS X (for a
    356     package or all executables in a distribution), where an empty
    357     string disables signing; the default is @racket[""]}
    358 
    359   @item{@racket[#:osslsigncode-args (list _string ...)] --- provides
    360     arguments for signing a Windows executable using
    361     @exec{osslsigncode}, where @Flag{n}, @Flag{t}, @Flag{in}, and
    362     @Flag{-out} arguments are supplied automatically.}
    363 
    364   @item{@racket[#:j _integer] --- parallelism for @tt{make} on Unix
    365     and Mac OS X and for @exec{raco setup} on all platforms; defaults
    366     to @racket[1]}
    367 
    368   @item{@racket[#:timeout _number] --- numbers of seconds to wait
    369     before declaring failure; defaults to 30 minutes}
    370 
    371   @item{@racket[#:clean? _boolean] --- if true, then the build process
    372     on the client machine starts by removing @racket[#:dir]'s value;
    373     use @racket[#f] for a shared repo checkout; the default is
    374     determined by the @tt{CLEAN_MODE} makefile variable, unless
    375     @racket[#:host] is @racket["localhost"], @racket[#:user] is
    376     @racket[#f], and @racket[#:dir] is not specified, in which case
    377     the default is @racket[#f]}
    378 
    379   @item{@racket[#:pull? _boolean] --- if true, then the build process
    380     on the client machine starts by a @exec{git pull} in
    381     @racket[#:dir]'s value; use @racket[#f], for example, for a repo
    382     checkout that is shared with server; the default is @racket[#t],
    383     unless @racket[#:host] is @racket["localhost"], @racket[#:user] is
    384     @racket[#f], and @racket[#:dir] is not specified, in which case
    385     the default is @racket[#f]}
    386 
    387   @item{@racket[#:release? _boolean] --- if true, then create
    388     release-mode installers; the default is determined by the
    389     @tt{RELEASE_MODE} makefile variable}
    390 
    391   @item{@racket[#:source? _boolean] --- determines the default value for
    392     @racket[#:source-runtime?] and @racket[#:source-pkgs] settings}
    393 
    394   @item{@racket[#:source-runtime? _boolean] --- if true, then create
    395     an archive that contains the run-time system in source form
    396     (possibly with built packages), instead of a platform-specific
    397     installer; a @racket[#t] value works best when used for a Unix
    398     build, since Unix clients typically have no
    399     native-library packages; the default is the value of
    400     @racket[#:source?]}
    401 
    402   @item{@racket[#:source-pkgs? _boolean] --- if true, then packages
    403     are included in the installer/archive only in source form; a true
    404     value works best when the @racket[#:source-runtime?] value is also
    405     @racket[#t]; the default is the value of @racket[#:source?]}
    406 
    407   @item{@racket[#:versionless? _boolean] --- if true, avoids including
    408     the Racket version number in an installer's name or in the
    409     installation path; the default is determined by the
    410     @tt{VERSIONLESS_MODE} makefile variable}
    411 
    412   @item{@racket[#:mac-pkg? _boolean] --- if true, creates a
    413     @filepath{.pkg} for Mac OS X (in single-file format) instead of a
    414     @filepath{.dmg}; the default is @racket[#f]}
    415 
    416   @item{@racket[#:tgz? _boolean] --- if true, creates a
    417     @filepath{.tgz} archive instead of an installer; the default is
    418     @racket[#f]}
    419 
    420   @item{@racket[#:pause-before _nonnegative-real] --- a pause in
    421     seconds to wait before starting a machine, which may help a
    422     virtual machine avoid confusion from being stopped and started too
    423     quickly; the default is @racket[0]}
    424 
    425   @item{@racket[#:pause-after _nonnegative-real] --- a pause in
    426     seconds to wait after stopping a machine; the default is
    427     @racket[0]}
    428 
    429   @item{@racket[#:custom _hash-table] --- a hash table mapping
    430     arbitrary keywords to arbitrary values; when a value for
    431     @racket[#:custom] is overriden in a nested configuration, the new
    432     table is merged with the overriden one; use such a table for
    433     additional configuration entries other than the built-in ones,
    434     where additional entires may be useful to a @racket[#:readme]
    435     procedure}
    436 
    437 ]
    438 
    439 Top keywords (recognized only in the configuration top-level):
    440 
    441 @itemlist[
    442 
    443   @item{@racket[#:site-dest _path-string] --- destination for
    444     completed build, used by the @tt{site} and @tt{snapshot-site}
    445     makefile targets; the default is @racket["build/site"]}
    446 
    447   @item{@racket[#:pdf-doc? _boolean] --- whether to build PDF
    448     documentation when assembling a site; the default is @racket[#f]}
    449 
    450   @item{@racket[#:email-to (list _string ...)] --- a list of addresses
    451      to receive e-mail reporting build results; mail is sent via
    452      @exec{sendmail} unless @racket[#:smtp-...] configuration is
    453      supplied}
    454 
    455   @item{@racket[#:email-from _string] --- address used as the sender
    456     of e-mailed reports; the first string in @racket[#:email-to] is
    457     used by default}
    458 
    459   @item{@racket[#:smtp-server _string*],
    460         @racket[#:smtp-port _string*],
    461         @racket[#:smtp-connect _symbol],
    462         @racket[#:smtp-user _string-or-false]
    463         @racket[#:smtp-password _string-or-false]
    464     --- configuration for sending e-mail through SMTP instead of
    465     @exec{sendmail}; the @racket[#:smtp-port] default (@racket[25],
    466     @racket[465], or @racket[587]) is picked based on
    467     @racket[#:smtp-connect], which can be @racket['plain],
    468     @racket['ssl], or @racket['tls] and defaults to @racket['plain];
    469     supply a non-@racket[#f] @racket[#:smtp-user] and
    470     @racket[#:smtp-password] when authentication is required by the
    471     server}
    472 
    473   @item{@racket[#:site-help _hash-table] --- hash table of extra
    474     ``help'' information for entries on a web page created by the
    475     @tt{site} and @tt{snapshot-site} makefile targets; the hash keys
    476     are strings for row labels in the download table (after splitting
    477     on @litchar{|} and removing @litchar["{"]...@litchar["}"]), and
    478     the values are X-expressions (see @racketmodname[xml]) for the
    479     help content}
    480 
    481   @item{@racket[#:site-title _string] --- title for the main page
    482     generated by the @tt{site} or @tt{snapshot-site} makefile target;
    483     the default is @racket["Racket Downloads"]}
    484 
    485   @item{@racket[#:max-snapshots _number] --- number of snapshots to
    486     keep, used by the @tt{snapshot-site} makefile target}
    487 
    488   @item{@racket[#:plt-web-style? _boolean] --- indicates whether
    489     @racket[plt-web] should be used to generate a site or snapshot
    490     page; the default is @racket[#t]}
    491 
    492 ]}
    493 
    494 
    495 @deftogether[(
    496 @defproc[(site-config? [v any/c]) boolean?]
    497 @defproc[(site-config-tag [config site-config?])
    498          (or/c 'machine 'sequential 'parallel)]
    499 @defproc[(site-config-options [config site-config?])
    500          (hash/c keyword? any/c)]
    501 @defproc[(site-config-content [config site-config?])
    502          (listof site-config?)]
    503 )]{
    504 
    505 Recognize and inspect site configurations.}
    506 
    507 
    508 @defparam[current-mode s string?]{
    509 
    510 A parameter whose value is the user's requested mode for this
    511 configuration, normally as provided via the makefile's
    512 @tt{CONFIG_MODE} variable. The default mode is @racket["default"]. The
    513 interpretation of modes is completely up to the site configuration
    514 file.}
    515 
    516 
    517 @defproc[(current-stamp) string?]{
    518 
    519 Returns a string to identify the current build, normally a combination
    520 of the date and a git commit hash.}
    521 
    522 
    523 @; ----------------------------------------
    524 
    525 @section{READMEs}
    526 
    527 @defmodule[distro-build/readme]{The
    528 @racketmodname[distro-build/readme] library provides functions for
    529 constructing a @filepath{README} file's content. Each function takes a
    530 hash table mapping configuration keywords to values.}
    531 
    532 @defproc[(make-readme [config hash?]) string?]{
    533 
    534 Produces basic @filepath{README} content, using information about the
    535 distribution and the Racket license. The content is constructed using
    536 @racket[config] keys such as @racket[#:name], @racket[#:target-platform],
    537 @racket[#:dist-name], and @racket[#:dist-catalogs], and sometimes
    538 @racket[current-stamp]. Some content depends on the result of
    539 @racket[(readme-system-type config)].}
    540 
    541 
    542 @defproc[(make-macosx-notes [config hash?]) string?]{
    543 
    544 Produces @filepath{README} content to tell Mac OS X users how to install a
    545 distribution folder. This function is used by @racket[make-readme] when
    546 @racket[#:platform] in @racket[config] is @racket['macosx].}
    547 
    548 
    549 @defproc[(readme-system-type [config hash?]) (or/c 'unix 'macosx 'windows)]{
    550 
    551 Determines the kind of platform for a generated @filepath{README}
    552 file:
    553 
    554 @itemlist[
    555 
    556  @item{If @racket['#:target-platform] has a non-@racket[#f] value in
    557        @racket[config], the value is returned.}
    558 
    559  @item{Otherwise, if @racket['#:cross-target] has a string value, then
    560        a system type is inferred if it contains any of the following
    561        fragments: @litchar{mingw} implies @racket['windows],
    562        @litchar{darwin} implies @racket['macosx], and @litchar{linux}
    563        implies @racket['unix].}
    564 
    565  @item{If the above fail, the value of @racket['#:platform] is
    566        returned, if it is mapped in @racket[config].}
    567 
    568  @item{As a last resort, @racket[(system-type)] is returned.}
    569 
    570 ]}
    571 
    572 @; ----------------------------------------
    573 
    574 @section[#:tag "name-format"]{Names and Download Pages}
    575 
    576 The @racket[#:name] value for an installer is used in an HTML table of
    577 download links by the @tt{site} or @tt{snapshot-site} targets. The
    578 names are first sorted. Then, for the purposes of building the table,
    579 a @litchar["|"] separated by any number of spaces within a name is
    580 treated as a hierarchical delimiter, while anything within
    581 @litchar["{"] and @litchar["}"] in a hierarchical level is stripped
    582 from the displayed name along with surrounding spaces (so that it can
    583 affect sorting without being displayed). Anything after
    584 @litchar[";\x20"] within a @litchar{|}-separated part is rendered as a
    585 detail part of the label (e.g., in a smaller font).
    586 
    587 For example, the names
    588 
    589 @racketblock[
    590   "Racket | {2} Linux | 32-bit"
    591   "Racket | {2} Linux | 64-bit; built on Ubuntu"
    592   "Racket | {1} Windows | 32-bit"
    593   "Racket | {1} Windows | 64-bit"
    594   "Racket | {3} Source"
    595 ]
    596 
    597 are shown (actually or conceptually) as
    598 
    599 @verbatim[#:indent 2]|{
    600   Racket
    601    Windows
    602      [32-bit] <built on Ubuntu>
    603      [64-bit]
    604    Linux
    605      [32-bit]
    606      [64-bit]
    607    [Source]
    608 }|
    609 
    610 where the square-bracketed entries are hyperlinks and the
    611 angle-bracketed pieces are details.
    612 
    613 @; ----------------------------------------
    614 
    615 @section{Examples}
    616 
    617 Here are some example configuration files.
    618 
    619 @subsection{Single Installer}
    620 
    621 The simplest possible configuration file is
    622 
    623 @codeblock{
    624   #lang distro-build/config
    625   (machine)
    626 }
    627 
    628 In fact, this configuration file is created automatically as
    629 @filepath{build/site.rkt} (if the file does not exist already) and
    630 used as the default configuration. With this configuration,
    631 
    632 @commandline{make installers}
    633 
    634 creates an installer in @filepath{build/installers} for the platform
    635 that is used to create the installer.
    636 
    637 
    638 @subsection{Installer Web Page}
    639 
    640 To make a web page that serves both a minimal installer and packages,
    641 create a @filepath{site.rkt} file with
    642 
    643 @codeblock{
    644  #lang distro-build/config
    645 
    646  (sequential
    647   ;; The packages that will be available:
    648   #:pkgs '("main-distribution")
    649   ;; FIXME: the URL where the installer and packages will be:
    650   #:dist-base-url "http://my-server.domain/snapshot/"
    651   (machine
    652    ;; FIXME: the way the installer is described on the web page:
    653    #:name "Minimal Racket | My Platform" 
    654    ;; The packages in this installer:
    655    #:pkgs '()))
    656 }
    657 
    658 then
    659 
    660 @commandline{make site CONFIG=site.rkt}
    661 
    662 creates a @filepath{build/site} directory that you can move to your
    663 web server's @filepath{snapshot} directory, so that
    664 @filepath{build/site/index.html} is the main page, and so on.
    665 
    666 
    667 @subsection{Accumulated Shapshots Web Page}
    668 
    669 To make a web site that provides some number (5, by default) of
    670 snapshots, use @racket[(current-stamp)] when constructing the
    671 @racket[#:dist-base-url] value. Also, use @racket[(current-stamp)] as
    672 the directory for assembling the site:
    673 
    674 @codeblock{
    675  #lang distro-build/config
    676  (sequential
    677   ;; The packages that will be available:
    678   #:pkgs '("gui-lib")
    679   ;; FIXME: the URL where the installer and packages will be:
    680   #:dist-base-url (string-append "http://my-server.domain/snapshots/"
    681                                  (current-stamp) "/")
    682   ;; The local directory where a snapshot is written
    683   #:site-dest (build-path "build/site" (current-stamp))
    684   (machine
    685    ;; FIXME: the way the installer is described on the web page:
    686    #:name "Minimal Racket | My Platform" 
    687    ;; The packages in this installer:
    688    #:pkgs '()))
    689 }
    690 
    691 Then,
    692 
    693 @commandline{make snapshot-site CONFIG=site.rkt}
    694 
    695 creates a @filepath{build/site} directory that you can move to your web
    696 server's @filepath{snapshots} directory, so that @filepath{build/site/index.html} is the
    697 main page that initially points to @filepath{build/site/@nonterm{stamp}/index.html},
    698 and so on. To make a newer snapshot, update the Git repository, leave
    699 @filepath{build/site} in place, and run
    700 
    701 @commandline{make snapshot-site CONFIG=site.rkt}
    702 
    703 again. The new installers will go into a new <stamp> subdirectory, and
    704 the main @filepath{index.html} file will be rewritten to point to them.
    705 
    706 
    707 @subsection{Multiple Platforms}
    708 
    709 A configuration module that drives multiple clients to build
    710 installers might look like this:
    711 
    712 @codeblock{
    713     #lang distro-build/config
    714    
    715     (sequential
    716      #:pkgs '("drracket")
    717      #:server-hosts '() ; Insecure? See below.
    718      (machine
    719       #:desc "Linux (32-bit, Precise Pangolin)"
    720       #:name "Ubuntu 32"
    721       #:vbox "Ubuntu 12.04"
    722       #:host "192.168.56.102")
    723      (machine
    724       #:desc "Windows (64-bit)"
    725       #:name "Windows 64"
    726       #:host "10.0.0.7"
    727       #:server "10.0.0.1"
    728       #:dir "c:\\Users\\racket\\build\\plt"
    729       #:platform 'windows
    730       #:bits 64))
    731 }
    732 
    733 The configuration describes using the hosts @racket["192.168.56.1"]
    734 and @racket["10.0.0.7"] for Linux and Windows builds, respectively,
    735 which are run one at a time.
    736 
    737 The Linux machine runs in VirtualBox on the server machine (in a
    738 virtual machine named @filepath{Ubuntu 12.04}). It contacts the server
    739 still as @tt{localhost}, and that works because the SSH connection to
    740 the Linux machine creates a tunnel (at the same port as the server's,
    741 which defaults to 9440).
    742 
    743 The Windows machine uses freeSSHd (not a @exec{bash}-based SSH server
    744 like Cygwin) and communicates back to the server as
    745 @racket["10.0.0.1"] instead of using an SSH tunnel. To make that work,
    746 @racket[#:server-hosts] is specified as the empty list to make the
    747 server listen on all interfaces (instead of just
    748 @racket["localhost"])---which is possibly less secure than the default
    749 restriction that allows build-server connections only via
    750 @racket["localhost"].
    751 
    752 With this configuration file in @filepath{site.rkt},
    753 
    754 @commandline{make installers CONFIG=site.rkt}
    755 
    756 produces two installers, both in @filepath{build/installers}, and a
    757 hash table in @filepath{table.rktd} that maps
    758 @racket["Linux (32-bit, Precise Pangolin)"] to the Linux installer
    759 and @racket["Windows (64-bit)"] to the Windows installer.