build-system/python: Memoize the results of 'package-with-python2'.

Fixes <http://bugs.gnu.org/21675>.
Reported by Cyril Roelandt <tipecaml@gmail.com>.

Before this change, the command:

  guix build python2-oslo.utils -n --no-substitutes

would take 17.5s.  After, it is down to 2.9s.
Likewise, the command:

  guix graph python2-bandit | grep python2-setuptools.*Helve| wc -l

would return 412 nodes before, all functionally equivalent, and returns
a single one now.

* guix/build-system/python.scm (package-with-explicit-python): Remove
  'p' parameter.  Change to return a one-argument memoizing procedure.
  (package-with-python2): Adjust accordingly.
This commit is contained in:
Ludovic Courtès 2015-10-12 23:44:39 +02:00
parent c80f1559eb
commit b3e2a5af9f

View file

@ -56,19 +56,25 @@ (define (default-python2)
(let ((python (resolve-interface '(gnu packages python)))) (let ((python (resolve-interface '(gnu packages python))))
(module-ref python 'python-2))) (module-ref python 'python-2)))
(define (package-with-explicit-python p python old-prefix new-prefix) (define (package-with-explicit-python python old-prefix new-prefix)
"Create a package with the same fields as P, which is assumed to use "Return a procedure of one argument, P. The procedure creates a package with
PYTHON-BUILD-SYSTEM, such that it is compiled with PYTHON instead. The the same fields as P, which is assumed to use PYTHON-BUILD-SYSTEM, such that
inputs are changed recursively accordingly. If the name of P starts with it is compiled with PYTHON instead. The inputs are changed recursively
OLD-PREFIX, this is replaced by NEW-PREFIX; otherwise, NEW-PREFIX is accordingly. If the name of P starts with OLD-PREFIX, this is replaced by
prepended to the name." NEW-PREFIX; otherwise, NEW-PREFIX is prepended to the name."
(define transform
;; Memoize the transformations. Failing to do that, we would build a huge
;; object graph with lots of duplicates, which in turns prevents us from
;; benefiting from memoization in 'package-derivation'.
(memoize ;FIXME: use 'eq?'
(lambda (p)
(let* ((rewrite-if-package (let* ((rewrite-if-package
(lambda (content) (lambda (content)
;; CONTENT may be a file name, in which case it is returned, or a ;; CONTENT may be a file name, in which case it is returned,
;; package, which is rewritten with the new PYTHON and NEW-PREFIX. ;; or a package, which is rewritten with the new PYTHON and
;; NEW-PREFIX.
(if (package? content) (if (package? content)
(package-with-explicit-python content python (transform content)
old-prefix new-prefix)
content))) content)))
(rewrite (rewrite
(match-lambda (match-lambda
@ -76,11 +82,13 @@ (define (package-with-explicit-python p python old-prefix new-prefix)
(append (list name (rewrite-if-package content)) rest))))) (append (list name (rewrite-if-package content)) rest)))))
(if (eq? (package-build-system p) python-build-system) (if (eq? (package-build-system p) python-build-system)
(package (inherit p) (package
(inherit p)
(name (let ((name (package-name p))) (name (let ((name (package-name p)))
(string-append new-prefix (string-append new-prefix
(if (string-prefix? old-prefix name) (if (string-prefix? old-prefix name)
(substring name (string-length old-prefix)) (substring name
(string-length old-prefix))
name)))) name))))
(arguments (arguments
(let ((arguments (package-arguments p)) (let ((arguments (package-arguments p))
@ -88,18 +96,21 @@ (define (package-with-explicit-python p python old-prefix new-prefix)
(force python) (force python)
python))) python)))
(if (member #:python arguments) (if (member #:python arguments)
(substitute-keyword-arguments arguments ((#:python p) python)) (substitute-keyword-arguments arguments
((#:python p) python))
(append arguments `(#:python ,python))))) (append arguments `(#:python ,python)))))
(inputs (map rewrite (package-inputs p))) (inputs (map rewrite (package-inputs p)))
(propagated-inputs (map rewrite (package-propagated-inputs p))) (propagated-inputs (map rewrite (package-propagated-inputs p)))
(native-inputs (map rewrite (package-native-inputs p)))) (native-inputs (map rewrite (package-native-inputs p))))
p))) p)))))
transform)
(define package-with-python2 (define package-with-python2
;; Note: delay call to 'default-python2' until after the 'arguments' field ;; Note: delay call to 'default-python2' until after the 'arguments' field
;; of packages is accessed to avoid a circular dependency when evaluating ;; of packages is accessed to avoid a circular dependency when evaluating
;; the top-level of (gnu packages python). ;; the top-level of (gnu packages python).
(cut package-with-explicit-python <> (delay (default-python2)) (package-with-explicit-python (delay (default-python2))
"python-" "python2-")) "python-" "python2-"))
(define* (lower name (define* (lower name