From 51396e2baac9978cc35931e0b1b79d6533949fdf Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 12 Jun 2010 08:37:43 -0600 Subject: [PATCH] auto-download pre-built Win/Mac binaries during build --- src/README | 32 ++++----- src/gracket/Makefile.in | 17 +++-- src/gracket/get-libs.rkt | 148 +++++++++++++++++++++++++++++++++++++++ src/worksp/README | 12 +++- src/worksp/build.bat | 2 + 5 files changed, 186 insertions(+), 25 deletions(-) create mode 100644 src/gracket/get-libs.rkt diff --git a/src/README b/src/README index 1c2df8c6ba..4b33ddc871 100644 --- a/src/README +++ b/src/README @@ -41,11 +41,9 @@ the Unix instructions below, but note the following: installed into "racket/lib". This framework is used by the `racket' executable that goes into "racket/bin". - * The GRacket build creates a framework, "GRacket.framework", which is - installed into "racket/lib". This framework is used by the - executable bundle GRacket.app that goes into the "racket" directory. - The installation creates a script, "racket/bin/gracket", that runs - the bundle. + * The GRacket build creates a GUI-executable variant of the Racket + executable. The GRacket build process also downloads (from github) + pre-built libraries for Cairo, Pango, etc. * The `--enable-shared' flag for `configure' must not be used, because builds create and use frameworks by default. Furthermore, @@ -55,7 +53,9 @@ the Unix instructions below, but note the following: * To build an X11-based GRacket, run `configure' with the `--enable-xonx' flag. Frameworks are not used for such builds, so --enable-shared is allowed. The `--enable-xonx' flag also affects - the Racket build, so that `system-type' reports 'unix. + the Racket build, so that `system-type' reports 'unix. Pre-built + libraries are not downloaded in this more; you must have Cairo, + Pango, and GTk installed. * To use `--prefix' without `--enable-xonx', you must also supply `--enable-macprefix'. BEWARE! The directory structure for a @@ -67,10 +67,9 @@ the Unix instructions below, but note the following: directory structure on top of an existing Unix-style directory structure.) - * Under Mac OS X 10.6 and later, `configure' by default selects 32-bit - mode for building Racket and GRacket. To build Racket in 64-bit mode - (GRacket is not support in that mode), use the following arguments to - `configure': `--enable-mac64', `--enable-sgc', and `--disable-gracket'. + * Under Mac OS X 10.6 and later, `configure' by default selects + 32-bit mode for building Racket. To build Racket in 64-bit mode, + use `--enable-mac64'. ======================================================================== Compiling for supported Unix variants (including Linux) or Cygwin @@ -102,15 +101,10 @@ Detailed instructions: remove it (unless you are using an "in-place" build from a repository as described below). - Also, make sure that you have libraries and header files for Xft and - Cairo (v1.23 and up) if you would like support for font smoothing - (Xft) and graphics smoothing (Cairo). These libraries are not - distributed with Racket. The configure process checks automatically - whether these libraries are available. - - OpenGL support for GRacket sometimes requires special configuration - (though generally not under Linux). See the note at the end of this - section if OpenGL fails to work. + Also, make sure that you have libraries and header files for + Cairo, Pango, and GTk. These libraries are not distributed with + Racket. The configure process checks automatically whether these + libraries are available. Finally, the content of the "foreign" subdirectory may require GNU `make'. If the build fails with another variant of `make', please diff --git a/src/gracket/Makefile.in b/src/gracket/Makefile.in index ce7339bf5d..aca682bec0 100644 --- a/src/gracket/Makefile.in +++ b/src/gracket/Makefile.in @@ -72,9 +72,11 @@ bin: $(MAKE) @MAIN_VARIANT@ 3m: + $(MAKE) libs/ready cd gc2; $(MAKE) 3m cgc: + $(MAKE) libs/ready $(MAKE) $(LINKRESULT) both: @@ -121,6 +123,9 @@ grmain_ee.@LTO@ : gracket.@LTO@ ee-main: $(MAKE) grmain_ee.@LTO@ +libs/ready: + $(RACKET) -c "$(srcdir)/get-libs.rkt" --ready "$(srcdir)" libs + clean: rm -f *.@LTO@ *.d core gracket gracket3m rm -f gc2/*.@LTO@ gc2/xsrc/* gc2/macxsrc/* gc2/*.d gc2/*.dd @@ -155,16 +160,17 @@ install-post-collects: $(MAKE) install-@WXVARIANT@-post-collects install-common: - cd ..; rm -f "$(DESTDIR)$(bindir)/gracket@CGC_INSTALLED@" - cd ..; rm -f "$(DESTDIR)$(bindir)/gracket@MMM_INSTALLED@" - cd ..; echo 'MROPTIONS=@MROPTIONS@' >> $(BUILDINFO) - cd ..; echo "MRLIBS=$(GUILIBS_@WXVARIANT@)" >> $(BUILDINFO) - cd ..; echo "MRLDFLAGS=$(GRACKETLDFLAGS)" >> $(BUILDINFO) + $(RACKET) -c "$(srcdir)/get-libs.rkt" --install . "$(DESTDIR)$(libpltdir)" # X11 ---------------------------------------- install-wx_xt: $(MAKE) install-common + cd ..; rm -f "$(DESTDIR)$(bindir)/gracket@CGC_INSTALLED@" + cd ..; rm -f "$(DESTDIR)$(bindir)/gracket@MMM_INSTALLED@" + cd ..; echo 'MROPTIONS=@MROPTIONS@' >> $(BUILDINFO) + cd ..; echo "MRLIBS=$(GUILIBS_@WXVARIANT@)" >> $(BUILDINFO) + cd ..; echo "MRLDFLAGS=$(GRACKETLDFLAGS)" >> $(BUILDINFO) cd ..; mkdir -p "$(DESTDIR)$(bindir)" install-no-lib-cgc-wx_xt: @@ -203,6 +209,7 @@ install-wx_xt-post-collects: FRAMEWORK_REL_PREFIX="@executable_path/../../../lib/" install-wx_mac: + $(MAKE) install-common cd ..; rm -rf "$(prefix)/GRacket@CGC_CAP_INSTALLED@.app" cd ..; rm -rf "$(prefix)/GRacket@MMM_CAP_INSTALLED@.app" diff --git a/src/gracket/get-libs.rkt b/src/gracket/get-libs.rkt new file mode 100644 index 0000000000..f7e8652e48 --- /dev/null +++ b/src/gracket/get-libs.rkt @@ -0,0 +1,148 @@ +#lang racket/base +(require racket/cmdline + racket/tcp) +;; This program avoids racket/port and net/url, because +;; it is loaded without using bytecode. + +(define mode (make-parameter 'download)) +(define touch-ready? (make-parameter #f)) + +(define-values (src-dir dest-dir) + (command-line + #:once-any + [("--download") "download mode (the default)" (mode 'download)] + [("--install") "install mode" (mode 'install)] + #:once-each + [("--ready") "touch `ready' on download success" (touch-ready? #t)] + #:args + (src-dir dest-dir) + (values src-dir dest-dir))) + +(define url-host "github.com") +(define url-path "/mflatt/gracket-libs/raw/master/") +(define url-base (string-append "http://" url-host url-path)) + +(define needed-files + (case (system-type) + [(unix) + ;; Pre-built binaries are for Windows and Mac only + null] + [(macosx) + '("libcairo.2.dylib" + "libintl.8.dylib" + "libgio-2.0.0.dylib" + "libjpeg.62.dylib" + "libglib-2.0.0.dylib" + "libpango-1.0.0.dylib" + "libgmodule-2.0.0.dylib" + "libpangocairo-1.0.0.dylib" + "libgobject-2.0.0.dylib" + "libpixman-1.0.dylib" + "libgthread-2.0.0.dylib" + "libpng14.14.dylib")] + [(windows) + '("freetype6.dll" + "libgobject-2.0-0.dll" + "libatk-1.0-0.dll" + "libgtk-win32-2.0-0.dll" + "libcairo-2.dll" + "libjpeg-7.dll" + "libexpat-1.dll" + "libpango-1.0-0.dll" + "libfontconfig-1.dll" + "libpangocairo-1.0-0.dll" + "libgdk-win32-2.0-0.dll" + "libpangoft2-1.0-0.dll" + "libgdk_pixbuf-2.0-0.dll" + "libpangowin32-1.0-0.dll" + "libgio-2.0-0.dll" + "libpng14-14.dll" + "libglib-2.0-0.dll" + "libwimp.dll" + "libgmodule-2.0-0.dll" + "zlib1.dll" + "gtkrc")])) + +(define explained? #f) + +(define (purify-port port) + (let ([m (regexp-match-peek-positions + #rx"^HTTP/.*?(?:\r\n\r\n|\n\n|\r\r)" port)]) + (if m (read-string (cdar m) port) ""))) + +(define (copy-port src dest) + (let ([s (make-bytes 4096)]) + (let loop () + (let ([c (read-bytes-avail! s src)]) + (cond + [(number? c) + (let loop ([start 0]) + (unless (= start c) + (let ([c2 (write-bytes-avail s dest start c)]) + (loop (+ start c2))))) + (loop)] + [else + ;; Must be EOF + (void)]))))) + +(define (download-if-needed dest-dir file) + (let ([dest (build-path dest-dir file)] + [tmp (build-path dest-dir (format "~a.download" file))]) + (if (file-exists? dest) + (printf " ~a is ready\n" file) + (let ([src (format "~a~a/~a" + url-path + (system-library-subpath #f) + file)]) + (unless explained? + (set! explained? #t) + (printf ">> Downloading files from\n>> ~a~a\n" url-base (system-library-subpath #f)) + (printf ">> If you don't want automatic download, downlaod each file\n") + (printf ">> yourself from there to\n") + (printf ">> ~a\n" (path->complete-path dest-dir))) + (printf " ~a downloading..." file) + (flush-output) + (let-values ([(i o) (tcp-connect url-host 80)]) + (fprintf o "GET ~a HTTP/1.0\r\n" (string-append src)) + (fprintf o "Host: ~a\r\n" url-host) + (fprintf o "\r\n") + (flush-output o) + (tcp-abandon-port o) + (purify-port i) + (call-with-output-file tmp + #:exists 'truncate/replace + (lambda (out) + (copy-port i out))) + (rename-file-or-directory tmp dest #t) + (printf "done\n")))))) + +(define (same-content? f1 f2) + ;; approximate: + (and (file-exists? f1) + (file-exists? f2) + (= (file-size f1) (file-size f2)))) + +(define (install-file src dest) + (unless (same-content? src dest) + (printf "Updating ~a\n" dest) + (when (file-exists? dest) + (delete-file dest)) + (copy-file src dest))) + +(case (mode) + [(download) + (let ([libs dest-dir]) + (unless (directory-exists? libs) + (make-directory libs)) + (for-each (lambda (file) + (download-if-needed libs file)) + needed-files) + (when (touch-ready?) + (let ([ok (build-path libs "ready")]) + (unless (file-exists? ok) + (with-output-to-file ok void)))))] + [(install) + (for-each (lambda (file) + (install-file (build-path src-dir "libs" file) + (build-path dest-dir file))) + needed-files)]) diff --git a/src/worksp/README b/src/worksp/README index d46055e167..a8c5e86845 100644 --- a/src/worksp/README +++ b/src/worksp/README @@ -103,6 +103,16 @@ In addition, building RacketCGC executes which copies .exp, .obj, and .lib files into racket\lib\, and also copies DLLs from the "extradlls" directory to to racket\lib\. +Finally, you must install pre-build DLLs that GRacket needs to run. +The DLLs are available from + + http://github.com/mflatt/gracket-libs/tree/master/win32/i386/?raw=true + +and they must be installed into + + racket\lib + + Building Racket3m and GRacket3m ------------------------------- @@ -118,7 +128,7 @@ After RacketCGC and GRacketCGC are built, you can can build 3m binaries: The resulting Racket.exe and GRacket.exe will appear in the top-level "racket" directory, along with DLLs libracket3mxxxxxxx.dll and -libgracket3mxxxxxxx.dll in racket/lib. (There is no corresponding +libgracket3mxxxxxxx.dll in racket\lib. (There is no corresponding libmzgc3mxxxxxxx.dll. Instead, it is merged with libracket3mxxxxxxx.dll.) diff --git a/src/worksp/build.bat b/src/worksp/build.bat index 4e1b19eecb..40eb0a86b5 100644 --- a/src/worksp/build.bat +++ b/src/worksp/build.bat @@ -8,6 +8,8 @@ cd gc2 ..\..\..\racketcgc -cu make.rkt cd .. +..\..\..\racketcgc -cu ..\gracket\get-libs.rkt ..\gracket ..\..\lib + cd mzcom devenv mzcom.sln /Build Release cd ..\libmysterx