commit 8a1d196ff30b26049397ff389f509a34e57ca70f
parent cf4e6d2b8a8904f25a015db60dc7b2c6380e477c
Author: Matthew Flatt <mflatt@racket-lang.org>
Date: Sat, 29 Aug 2015 18:10:10 -0600
support cross-compilation of installers
At least, support Windows installer creation on a non-Windows
machine.
Diffstat:
8 files changed, 71 insertions(+), 20 deletions(-)
diff --git a/distro-build-client/installer-dmg.rkt b/distro-build-client/installer-dmg.rkt
@@ -5,7 +5,8 @@
racket/runtime-path
ds-store
ds-store/alias
- compiler/exe-dylib-path)
+ compiler/exe-dylib-path
+ setup/cross-system)
(provide installer-dmg
make-dmg)
@@ -148,7 +149,7 @@
(define (installer-dmg human-name base-name dist-suffix readme sign-identity)
(define dmg-name (format "bundle/~a-~a~a.dmg"
base-name
- (system-library-subpath #f)
+ (cross-system-library-subpath #f)
dist-suffix))
(make-dmg human-name "bundle/racket" dmg-name bg-image readme sign-identity)
dmg-name)
diff --git a/distro-build-client/installer-exe.rkt b/distro-build-client/installer-exe.rkt
@@ -4,7 +4,8 @@
racket/system
racket/path
racket/runtime-path
- setup/getinfo)
+ setup/getinfo
+ setup/cross-system)
(provide installer-exe)
@@ -405,15 +406,21 @@ SectionEnd
(display script o)
(newline o)))
(parameterize ([current-directory "bundle"])
- (system* makensis "/V3" "installer.nsi")))
+ (define verbose (if (eq? 'windows (system-type))
+ "/V3"
+ "-V3"))
+ (system* makensis verbose "installer.nsi")))
(define (installer-exe human-name base-name versionless? dist-suffix readme)
- (define makensis (or (find-executable-path "makensis.exe")
- (try-exe "c:\\Program Files\\NSIS\\makensis.exe")
- (try-exe "c:\\Program Files (x86)\\NSIS\\makensis.exe")
+ (define makensis (or (case (system-type)
+ [(windows)
+ (or (find-executable-path "makensis.exe")
+ (try-exe "c:\\Program Files\\NSIS\\makensis.exe")
+ (try-exe "c:\\Program Files (x86)\\NSIS\\makensis.exe"))]
+ [else (find-executable-path "makensis")])
(error 'installer-exe "cannot find \"makensis.exe\"")))
- (define platform (let-values ([(base name dir?) (split-path (system-library-subpath #f))])
- (path->string name)))
+ (define platform (let-values ([(base name dir?) (split-path (cross-system-library-subpath #f))])
+ (bytes->string/utf-8 (path-element->bytes name))))
(define exe-path (format "bundle/~a-~a-win32~a.exe" base-name platform dist-suffix))
(when readme
(call-with-output-file*
diff --git a/distro-build-client/installer-pkg.rkt b/distro-build-client/installer-pkg.rkt
@@ -5,7 +5,8 @@
racket/runtime-path
ds-store
ds-store/alias
- xml)
+ xml
+ setup/cross-system)
(provide installer-pkg)
@@ -151,7 +152,7 @@
(define (installer-pkg human-name base-name dist-suffix readme sign-identity)
(define pkg-name (format "bundle/~a-~a~a.pkg"
base-name
- (system-library-subpath #f)
+ (cross-system-library-subpath #f)
dist-suffix))
(make-pkg human-name "bundle/racket" pkg-name readme sign-identity)
pkg-name)
diff --git a/distro-build-client/installer-sh.rkt b/distro-build-client/installer-sh.rkt
@@ -4,6 +4,7 @@
racket/port
racket/format
racket/runtime-path
+ setup/cross-system
file/tar)
(provide installer-sh)
@@ -78,7 +79,7 @@
(define (installer-sh human-name base-name dir-name release? dist-suffix readme)
(define sh-path (format "bundle/~a-~a~a.sh"
base-name
- (system-library-subpath #f)
+ (cross-system-library-subpath #f)
dist-suffix))
(generate-installer-sh "bundle/racket" sh-path
dir-name human-name
diff --git a/distro-build-client/installer.rkt b/distro-build-client/installer.rkt
@@ -9,6 +9,7 @@
racket/file
racket/path
racket/port
+ setup/cross-system
"display-time.rkt")
(module test racket/base)
@@ -70,7 +71,7 @@
(define installer-file
(if source?
(installer-tgz base-name dir-name dist-suffix readme)
- (case (system-type)
+ (case (cross-system-type)
[(unix) (installer-sh human-name base-name dir-name release? dist-suffix readme)]
[(macosx) (if mac-pkg?
(installer-pkg (if (or release? versionless?)
diff --git a/distro-build-doc/distro-build.scrbl b/distro-build-doc/distro-build.scrbl
@@ -58,7 +58,7 @@ default accepts only connections via @racket["localhost"].
On the client machine, all work is performed at a specified directory
as specified by @racket[#:dir]. The directory defaults to
-@filepath{build/plt} (Unix, Mac OS X) or @filepath{build\plt}
+@filepath{build/plt} (Unix or Mac OS X) or @filepath{build\plt}
(Windows), except when the host is @racket["localhost"] and the client
is @racket[#f], in which case the current directory (i.e., the
server's directory) is used.
@@ -110,7 +110,7 @@ installers.
@section{Machine Requirements}
-Each Unix or Mac OS X @tech{client machines} needs the following available:
+Each Unix or Mac OS X @tech{client machine} needs the following available:
@itemlist[
@@ -120,6 +120,10 @@ Each Unix or Mac OS X @tech{client machines} needs the following available:
@item{@exec{gcc}, @exec{make}, etc.}
+ @item{when creating a Windows installer (via cross-compilation),
+ Nullsoft Scriptable Install System (NSIS) version 2.x with
+ @exec{makensis} in @envvar{PATH}}
+
]
Each Windows @tech{client machine} needs the following:
@@ -138,15 +142,18 @@ Each Windows @tech{client machine} needs the following:
or
@filepath{C:\Program Files (x86)\Microsoft Visual Studio @nonterm{vers}}}
- @item{Nullsoft Scriptable Install System (NSIS) verstion 2.x, installed
+ @item{Nullsoft Scriptable Install System (NSIS) version 2.x, installed
in the default folder:
@filepath{C:\Program Files\NSIS\makensis.exe}
or
@filepath{C:\Program Files (x86)\NSIS\makensis.exe}
- or installed so that @exec{makensis} in your @envvar{PATH}.}
+ or installed so that @exec{makensis} in @envvar{PATH}}
]
+Currently, Windows and Unix variants can be cross-compiled using a
+same-versioned native Racket installation on a client machine that
+runs Unix or Mac OS X.
@; ----------------------------------------
@@ -209,6 +216,13 @@ spaces, etc.):
directory if the host is @racket["localhost"] and the user is
@racket[#f]}
+ @item{@racket[#:env (list (list _string* _string) ...)] ---
+ environment-variable settings to prefix all client-machine
+ interactions for a Unix or Mac OS X client; for example
+ @racket['(("PATH" "/usr/local/bin:/usr/bin"))] configures the
+ client machine's @envvar{PATH} enviornment variable to have
+ only @filepath{/usr/local/bin} and @filepath{/usr/bin}}
+
@item{@racket[#:server _string*] --- the address of the server as
accessed by the client; when SSH remote tunneling works, then
@racket["localhost"] should work to reach the server; defaults to
@@ -234,6 +248,13 @@ spaces, etc.):
@item{@racket[#:pkgs (list _string* ...)] --- packages to install;
defaults to the @tt{PKGS} makefile variable}
+ @item{@racket[#:racket _string-or-false] --- path to a native Racket
+ executable when using the client machine for cross-compilation; if
+ the value is @racket[#f], the the Racket executable generated for
+ the client machine is used to prepare the installer; a
+ non-@racket[#f] typically must be combined with
+ @racket[#:configure] arguments to set up cross-compilation}
+
@item{@racket[#:dist-base-url _string] --- a URL that is used to
construct a default for @racket[#:doc-search] and
@racket[#:dist-catalogs], where the constructed values are
@@ -349,8 +370,8 @@ spaces, etc.):
@item{@racket[#:source-runtime? _boolean] --- if true, then create
an archive that contains the run-time system in source form
(possibly with built packages), instead of a platform-specific
- installer; a @racket[#t] value works best when used with a Unix
- client machine, since Unix clients typically have no
+ installer; a @racket[#t] value works best when used for a Unix
+ build, since Unix clients typically have no
native-library packages; the default is the value of
@racket[#:source?]}
diff --git a/distro-build-server/config.rkt b/distro-build-server/config.rkt
@@ -113,6 +113,7 @@
(define (check-group-keyword kw val)
(case kw
[(#:pkgs) (and (list? val) (andmap simple-string? val))]
+ [(#:racket) (or (not val) (string? val))]
[(#:doc-search) (string? val)]
[(#:dist-name) (string? val)]
[(#:dist-base) (simple-string? val)]
@@ -130,6 +131,13 @@
[(#:user) (or (not val) (simple-string? val))]
[(#:port) (port-no? val)]
[(#:dir) (path-string? val)]
+ [(#:env) (and (list? val)
+ (andmap (lambda (p)
+ (and (list? p)
+ (= 2 (length p))
+ (simple-string? (car p))
+ (string? (cadr p))))
+ val))]
[(#:vbox) (string? val)]
[(#:platform) (memq val '(unix macosx windows windows/bash))]
[(#:configure) (and (list? val) (andmap string? val))]
diff --git a/distro-build-server/drive-clients.rkt b/distro-build-server/drive-clients.rkt
@@ -239,6 +239,7 @@
(if l
(apply ~a #:separator " " l)
default-pkgs)))
+ (define racket (get-opt c '#:racket))
(define doc-search (choose-doc-search c default-doc-search))
(define dist-name (or (get-opt c '#:dist-name)
default-dist-name))
@@ -264,6 +265,9 @@
(~a " SERVER=" server
" SERVER_PORT=" server-port
" PKGS=" (q pkgs)
+ (if racket
+ (~a " PLAIN_RACKET=" (q racket))
+ "")
" DOC_SEARCH=" (q doc-search)
" DIST_DESC=" (q desc)
" DIST_NAME=" (q dist-name)
@@ -286,8 +290,15 @@
(define (unix-build c platform host port user server server-port repo clean? pull? readme)
(define dir (get-path-opt c '#:dir "build/plt" #:localhost (current-directory)))
+ (define env (get-opt c '#:env null))
(define (sh . args)
- (list "/bin/sh" "-c" (apply ~a args)))
+ (append
+ (if (null? env)
+ null
+ (list* "/usr/bin/env"
+ (for/list ([e (in-list env)])
+ (format "~a=~a" (car e) (cadr e)))))
+ (list "/bin/sh" "-c" (apply ~a args))))
(define j (or (get-opt c '#:j) 1))
(try-until-ready c host port user server-port 'unix (sh "echo hello"))
(ssh-script