pull: Add a compilation progress report.

* guix/build/pull.scm (report-build-progress): New procedure.
  (p-for-each): Add #:progress parameter.
  [loop]: Keep track of the number of completed processes.  Tail-call
  PROGRESS at each loop iteration.
  (build-guix): Add #:debug-port parameter.  Use it for verbose
  messages.  Change 'tar' flags to 'xf'.  Around 'compile-file' call,
  bind CURRENT-WARNING-PORT to DEBUG-PORT.
* guix/scripts/pull.scm (unpack): Add #:verbose? parameter.
  [builder]: Pass #:debug-port to 'build-guix'.
  (guix-pull): Leave CURRENT-BUILD-OUTPUT-PORT unchanged.  Pass
  #:verbose? to 'unpack'.
master
Ludovic Courtès 2014-09-05 23:11:04 +02:00
parent 6fd1a79674
commit b50c5b7418
2 changed files with 65 additions and 31 deletions

View File

@ -21,6 +21,7 @@
#:use-module (system base compile) #:use-module (system base compile)
#:use-module (ice-9 ftw) #:use-module (ice-9 ftw)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (ice-9 format)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-11) #:use-module (srfi srfi-11)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
@ -47,43 +48,70 @@ normally, and 1 if an exception is raised."
(pid (pid
#t))) #t)))
(define* (report-build-progress total completed cont
#:optional (log-port (current-error-port)))
"Report that COMPLETED out of TOTAL files have been completed, and call
CONT."
(display #\cr log-port)
(format log-port "compiling...\t~5,1f% of ~d files" ;FIXME: i18n
(* 100. (/ completed total)) total)
(force-output log-port)
(cont))
(define* (p-for-each proc lst (define* (p-for-each proc lst
#:optional (max-processes (current-processor-count))) #:optional (max-processes (current-processor-count))
#:key (progress report-build-progress))
"Invoke PROC for each element of LST in a separate process, using up to "Invoke PROC for each element of LST in a separate process, using up to
MAX-PROCESSES processes in parallel. Raise an error if one of the processes MAX-PROCESSES processes in parallel. Call PROGRESS at each step, passing it
exit with non-zero." the continuation. Raise an error if one of the processes exit with non-zero."
(define total
(length lst))
(define (wait-for-one-process) (define (wait-for-one-process)
(match (waitpid WAIT_ANY) (match (waitpid WAIT_ANY)
((_ . status) ((_ . status)
(unless (zero? (status:exit-val status)) (unless (zero? (status:exit-val status))
(error "process failed" proc status))))) (error "process failed" proc status)))))
(let loop ((lst lst) (let loop ((lst lst)
(running 0)) (running 0)
(completed 0))
(match lst (match lst
(() (()
(or (zero? running) (or (zero? running)
(begin (let ((running (- running 1))
(completed (+ completed 1)))
(wait-for-one-process) (wait-for-one-process)
(loop lst (- running 1))))) (progress total completed
(lambda ()
(loop lst running completed))))))
((head . tail) ((head . tail)
(if (< running max-processes) (if (< running max-processes)
(begin (let ((running (+ 1 running)))
(call-with-process (cut proc head)) (call-with-process (cut proc head))
(loop tail (+ running 1))) (progress total completed
(begin (lambda ()
(loop tail running completed))))
(let ((running (- running 1))
(completed (+ completed 1)))
(wait-for-one-process) (wait-for-one-process)
(loop lst (- running 1)))))))) (progress total completed
(lambda ()
(loop lst running completed)))))))))
(define* (build-guix out tarball (define* (build-guix out tarball
#:key tar gzip gcrypt) #:key tar gzip gcrypt
"Build and install Guix in directory OUT using source from TARBALL." (debug-port (%make-void-port "w")))
"Build and install Guix in directory OUT using source from TARBALL. Write
any debugging output to DEBUG-PORT."
(setvbuf (current-output-port) _IOLBF) (setvbuf (current-output-port) _IOLBF)
(setvbuf (current-error-port) _IOLBF) (setvbuf (current-error-port) _IOLBF)
(setenv "PATH" (string-append tar "/bin:" gzip "/bin")) (setenv "PATH" (string-append tar "/bin:" gzip "/bin"))
(system* "tar" "xvf" tarball) (format debug-port "extracting '~a'...~%" tarball)
(system* "tar" "xf" tarball)
(match (scandir "." (lambda (name) (match (scandir "." (lambda (name)
(and (not (member name '("." ".."))) (and (not (member name '("." "..")))
(file-is-directory? name)))) (file-is-directory? name))))
@ -92,11 +120,13 @@ exit with non-zero."
(x (x
(error "tarball did not produce a single source directory" x))) (error "tarball did not produce a single source directory" x)))
(format #t "copying and compiling Guix to `~a'...~%" out) (format #t "copying and compiling to '~a'...~%" out)
;; Copy everything under guix/ and gnu/ plus {guix,gnu}.scm. ;; Copy everything under guix/ and gnu/ plus {guix,gnu}.scm.
(copy-recursively "guix" (string-append out "/guix")) (copy-recursively "guix" (string-append out "/guix")
(copy-recursively "gnu" (string-append out "/gnu")) #:log debug-port)
(copy-recursively "gnu" (string-append out "/gnu")
#:log debug-port)
(copy-file "guix.scm" (string-append out "/guix.scm")) (copy-file "guix.scm" (string-append out "/guix.scm"))
(copy-file "gnu.scm" (string-append out "/gnu.scm")) (copy-file "gnu.scm" (string-append out "/gnu.scm"))
@ -121,12 +151,12 @@ exit with non-zero."
(p-for-each (lambda (file) (p-for-each (lambda (file)
(let ((go (string-append (string-drop-right file 4) (let ((go (string-append (string-drop-right file 4)
".go"))) ".go")))
(format (current-error-port) (format debug-port "~%compiling '~a'...~%" file)
"compiling '~a'...~%" file) (parameterize ((current-warning-port debug-port))
(compile-file file (compile-file file
#:output-file go #:output-file go
#:opts #:opts
%auto-compilation-options))) %auto-compilation-options))))
(filter (cut string-suffix? ".scm" <>) (filter (cut string-suffix? ".scm" <>)
@ -144,6 +174,7 @@ exit with non-zero."
(delete-file (string-append out "/guix/config.scm")) (delete-file (string-append out "/guix/config.scm"))
(delete-file (string-append out "/guix/config.go")) (delete-file (string-append out "/guix/config.go"))
(newline)
#t) #t)
;;; pull.scm ends here ;;; pull.scm ends here

View File

@ -38,15 +38,21 @@
"http://git.savannah.gnu.org/cgit/guix.git/snapshot/guix-master.tar.gz" "http://git.savannah.gnu.org/cgit/guix.git/snapshot/guix-master.tar.gz"
) )
(define (unpack store tarball) (define* (unpack store tarball #:key verbose?)
"Return a derivation that unpacks TARBALL into STORE and compiles Scheme "Return a derivation that unpacks TARBALL into STORE and compiles Scheme
files." files."
(define builder (define builder
'(begin `(begin
(use-modules (guix build pull)) (use-modules (guix build pull))
(build-guix (assoc-ref %outputs "out") (build-guix (assoc-ref %outputs "out")
(assoc-ref %build-inputs "tarball") (assoc-ref %build-inputs "tarball")
;; XXX: This is not perfect, enabling VERBOSE? means
;; building a different derivation.
#:debug-port (if ',verbose?
(current-error-port)
(%make-void-port "w"))
#:tar (assoc-ref %build-inputs "tar") #:tar (assoc-ref %build-inputs "tar")
#:gzip (assoc-ref %build-inputs "gzip") #:gzip (assoc-ref %build-inputs "gzip")
#:gcrypt (assoc-ref %build-inputs "gcrypt")))) #:gcrypt (assoc-ref %build-inputs "gcrypt"))))
@ -129,13 +135,10 @@ Download and deploy the latest version of Guix.\n"))
(package-derivation store (package-derivation store
(if (assoc-ref opts 'bootstrap?) (if (assoc-ref opts 'bootstrap?)
%bootstrap-guile %bootstrap-guile
(canonical-package guile-2.0)))) (canonical-package guile-2.0)))))
(current-build-output-port
(if (assoc-ref opts 'verbose?)
(current-error-port)
(%make-void-port "w"))))
(let* ((config-dir (config-directory)) (let* ((config-dir (config-directory))
(source (unpack store tarball)) (source (unpack store tarball
#:verbose? (assoc-ref opts 'verbose?)))
(source-dir (derivation->output-path source))) (source-dir (derivation->output-path source)))
(if (show-what-to-build store (list source)) (if (show-what-to-build store (list source))
(if (build-derivations store (list source)) (if (build-derivations store (list source))