Skip to content

Commit

Permalink
make installers: support Mac OS X ".pkg" format
Browse files Browse the repository at this point in the history
The ".pkg"-based installer doesn't provide the option of picking
an installation path, but it can add a path in "/etc/paths.d"
so that users do not have to explicitly set the `PATH` environment
variable.
  • Loading branch information
mflatt committed Nov 11, 2013
1 parent 58261e3 commit 7dd10fc
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 11 deletions.
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ RELEASE_MODE =
# proper) on a client that has the run-time system in source form:
SOURCE_MODE =

# Set to "--mac-pkg" to create ".pkg"-based installers for Mac OS X,
# instead of a ".dmg" for drag-and-drop installation:
MAC_PKG_MODE =

# Set to "--source --no-setup" to include packages in an installer
# (or archive) only in source form:
PKG_SOURCE_MODE =
Expand Down Expand Up @@ -380,7 +384,7 @@ binary-catalog-server:

COPY_ARGS = SERVER=$(SERVER) SERVER_PORT=$(SERVER_PORT) SERVER_HOSTS="$(SERVER_HOSTS)" \
PKGS="$(PKGS)" BUILD_STAMP="$(BUILD_STAMP)" \
RELEASE_MODE=$(RELEASE_MODE) SOURCE_MODE=$(SOURCE_MODE) \
RELEASE_MODE=$(RELEASE_MODE) SOURCE_MODE=$(SOURCE_MODE) MAC_PKG_MODE=$(MAC_PKG_MODE) \
PKG_SOURCE_MODE="$(PKG_SOURCE_MODE)" INSTALL_NAME="$(INSTALL_NAME)"\
DIST_NAME="$(DIST_NAME)" DIST_BASE=$(DIST_BASE) \
DIST_DIR=$(DIST_DIR) DIST_SUFFIX=$(DIST_SUFFIX) \
Expand Down Expand Up @@ -426,7 +430,7 @@ bundle-config:
$(RACKET) -l distro-build/set-config $(SET_BUNDLE_CONFIG_q)

UPLOAD_q = --readme http://$(SVR_PRT)/$(README) --upload http://$(SVR_PRT)/ --desc "$(DIST_DESC)"
DIST_ARGS_q = $(UPLOAD_q) $(RELEASE_MODE) $(SOURCE_MODE) \
DIST_ARGS_q = $(UPLOAD_q) $(RELEASE_MODE) $(SOURCE_MODE) $(MAC_PKG_MODE) \
"$(DIST_NAME)" $(DIST_BASE) $(DIST_DIR) "$(DIST_SUFFIX)" \
"$(SIGN_IDENTITY)"

Expand Down
1 change: 1 addition & 0 deletions pkgs/distro-build/config.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
[(#:source?) (boolean? val)]
[(#:source-runtime?) (boolean? val)]
[(#:source-pkgs?) (boolean? val)]
[(#:mac-pkg?) (boolean? val)]
[(#:site-dest) (path-string? val)]
[(#:pdf-doc?) (boolean? val)]
[(#:max-snapshots) (real? val)]
Expand Down
5 changes: 4 additions & 1 deletion pkgs/distro-build/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ Site-configuration keywords (where <string*> means no spaces, etc.):
makefile variable

#:source? <boolean> --- determines the default value for
`#:source-runtime' and `#:source-pkgs'
`#:source-runtime?' and `#:source-pkgs'

#:source-runtime? <boolean> --- if true, then create an archive that
contains the run-time system in source form (possibly with built
Expand All @@ -258,6 +258,9 @@ Site-configuration keywords (where <string*> means no spaces, etc.):
when the `#:source-runtime?' value is also #t; the default is the
value of `#:source?'

#:mac-pkg? --- if true, creates a ".pkg" for Mac OS X (in
single-file format) instead of a ".dmg"; the default is #f

#:max-snapshots <number> --- number of snapshots to keep, used by
the `snapshot-site' makefile target

Expand Down
2 changes: 2 additions & 0 deletions pkgs/distro-build/drive-clients.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@
(define source? (get-opt c '#:source? #f))
(define source-pkgs? (get-opt c '#:source-pkgs? source?))
(define source-runtime? (get-opt c '#:source-runtime? source?))
(define mac-pkg? (get-opt c '#:mac-pkg? #f))
(define install-name (get-opt c '#:install-name (if release?
""
snapshot-install-name)))
Expand All @@ -301,6 +302,7 @@
" PKG_SOURCE_MODE=" (if source-pkgs?
(q "--source --no-setup")
(q ""))
" MAC_PKG_MODE=" (if mac-pkg? "--mac-pkg" (q ""))
" README=" (q (file-name-from-path readme))))

(define (unix-build c platform host port user server server-port repo clean? pull? readme)
Expand Down
134 changes: 134 additions & 0 deletions pkgs/distro-build/installer-pkg.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#lang at-exp racket/base
(require racket/system
racket/file
racket/format
racket/runtime-path
ds-store
ds-store/alias
xml)

(provide installer-pkg)

(define pkgbuild "/usr/bin/pkgbuild")
(define productbuild "/usr/bin/productbuild")

(define-runtime-path bg-image "macosx-installer/pkg-bg.png")

(define (system*/show . l)
(displayln (apply ~a #:separator " " l))
(flush-output)
(unless (apply system* l)
(error "failed")))

(define (gen-install-script install-dest)
(~a "#!/bin/sh\n"
"echo \"" (regexp-replace* #rx"\""
install-dest
"\"'\"'\"")
"\"/bin > /etc/paths.d/racket\n"))

(define (make-pkg human-name src-dir pkg-name readme sign-identity)
(define install-dest (string-append "/Applications/" human-name))
(define id (string-append "org.racket-lang."
(regexp-replace* #rx" "
human-name
"-")))

(define (make-rel dir-name)
(let-values ([(base name dir?) (split-path src-dir)])
(build-path base dir-name)))

(define work-dir (make-rel "work"))
(delete-directory/files work-dir #:must-exist? #f)
(define scripts-dir (make-rel "scripts"))
(delete-directory/files scripts-dir #:must-exist? #f)
(define resources-dir (make-rel "resources"))
(delete-directory/files resources-dir #:must-exist? #f)

(printf "Creating ~a\n" scripts-dir)
(make-directory* scripts-dir)
(define postinstall (build-path scripts-dir "postinstall"))
(call-with-output-file*
postinstall
(lambda (o)
(write-string (gen-install-script install-dest) o)))
(file-or-directory-permissions postinstall #o770)

(printf "Creating ~a\n" resources-dir)
(make-directory* resources-dir)
(copy-file bg-image (build-path resources-dir "background.png"))

(printf "Copying ~a\n" src-dir)
(define dest-dir work-dir)
(copy-directory/files src-dir dest-dir
#:keep-modify-seconds? #t)
(when readme
(call-with-output-file*
(build-path dest-dir "README.txt")
#:exists 'truncate
(lambda (o)
(display readme o))))
(copy-file (build-path dest-dir "README.txt")
(build-path resources-dir "README.txt"))

(apply system*/show
pkgbuild
(append
(list "--root" dest-dir
"--install-location" install-dest
"--scripts" scripts-dir
"--identifier" id
"--version" (version))
(if (string=? sign-identity "")
null
(list "--sign" sign-identity))
(list (make-rel "racket.pkg"))))
(define pkg-xml (make-rel "racket.xml"))
(system*/show productbuild
"--synthesize"
"--package" (make-rel "racket.pkg")
pkg-xml)
(define synthesized (call-with-input-file*
pkg-xml
read-xml))
(define updated
(struct-copy document synthesized
[element (let ([e (document-element synthesized)])
(struct-copy element e
[content
(list*
(element #f #f
'title
null
(list (pcdata #f #f human-name)))
(element #f #f
'readme
(list (attribute #f #f 'file "README.txt"))
null)
(element #f #f
'background
(list (attribute #f #f 'file "background.png")
(attribute #f #f 'alignment "topleft")
(attribute #f #f 'scaling "none"))
null)
(element-content e))]))]))
(call-with-output-file*
pkg-xml
#:exists 'truncate
(lambda (o)
(write-xml updated o)))
(system*/show productbuild
"--distribution" pkg-xml
"--package-path" (make-rel 'same)
"--resources" resources-dir
"--identifier" id
"--version" (version)
pkg-name))

(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)
dist-suffix))
(make-pkg human-name "bundle/racket" pkg-name readme sign-identity)
pkg-name)
9 changes: 8 additions & 1 deletion pkgs/distro-build/installer.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
(require racket/cmdline
"installer-sh.rkt"
"installer-dmg.rkt"
"installer-pkg.rkt"
"installer-exe.rkt"
"installer-tgz.rkt"
net/url
Expand All @@ -12,6 +13,7 @@

(define release? #f)
(define source? #f)
(define mac-pkg? #f)
(define upload-to #f)
(define upload-desc "")
(define download-readme #f)
Expand All @@ -23,6 +25,8 @@
(set! release? #t)]
[("--source") "Create a source installer"
(set! source? #t)]
[("--mac-pkg") "Create a \".pkg\" installer on Mac OS X"
(set! mac-pkg? #t)]
[("--upload") url "Upload installer"
(set! upload-to url)]
[("--desc") desc "Description to accompany upload"
Expand Down Expand Up @@ -58,7 +62,10 @@
(installer-tgz base-name dir-name dist-suffix readme)
(case (system-type)
[(unix) (installer-sh human-name base-name dir-name release? dist-suffix readme)]
[(macosx) (installer-dmg human-name base-name dist-suffix readme sign-identity)]
[(macosx) (if mac-pkg?
(installer-pkg (if release? short-human-name human-name)
base-name dist-suffix readme sign-identity)
(installer-dmg human-name base-name dist-suffix readme sign-identity))]
[(windows) (installer-exe short-human-name base-name release? dist-suffix readme)])))

(call-with-output-file*
Expand Down
Binary file added pkgs/distro-build/macosx-installer/pkg-bg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 17 additions & 7 deletions pkgs/distro-build/readme.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,20 @@
@~a{The distribution includes any pre-installed packages in source form.}]))

(define (make-macosx-notes config)
@~a{Install by dragging the enclosing
@|(hash-ref config '#:dist-name "Racket")| v@(version)
folder to your Applications folder --- or wherever you like. You can
move the folder at any time, but do not move applications or other
files within the folder. If you want to use the Racket command-line
programs, then (optionally) add the path of the "bin" subdirectory to
your PATH environment variable.})
(if (hash-ref config '#:mac-pkg? #f)
@~a{The installation directory is
/Applications/@(string-append
(hash-ref config '#:dist-name "Racket")
(if (hash-ref config '#:release? #f)
""
(string-append " v" (version))))
The installer also adjusts "/etc/paths.d/racket" to point to that
directory's "bin" directory, which adjusts the default PATH
environment variable for all users.}
@~a{Install by dragging the enclosing
@|(hash-ref config '#:dist-name "Racket")| v@(version)
folder to your Applications folder --- or wherever you like. You can
move the folder at any time, but do not move applications or other
files within the folder. If you want to use the Racket command-line
programs, then (optionally) add the path of the "bin" subdirectory to
your PATH environment variable.}))

0 comments on commit 7dd10fc

Please sign in to comment.