From b3e2a5af9ffa165b1131d5f5d6dec735d6a54c43 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Mon, 12 Oct 2015 23:44:39 +0200 Subject: build-system/python: Memoize the results of 'package-with-python2'. Fixes . Reported by Cyril Roelandt . 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. --- guix/build-system/python.scm | 91 +++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 40 deletions(-) (limited to 'guix/build-system') diff --git a/guix/build-system/python.scm b/guix/build-system/python.scm index e9fffcc62f..aeb04c83a4 100644 --- a/guix/build-system/python.scm +++ b/guix/build-system/python.scm @@ -56,51 +56,62 @@ (define (default-python2) (let ((python (resolve-interface '(gnu packages python)))) (module-ref python 'python-2))) -(define (package-with-explicit-python p python old-prefix new-prefix) - "Create a package with the same fields as P, which is assumed to use -PYTHON-BUILD-SYSTEM, such that it is compiled with PYTHON instead. The -inputs are changed recursively accordingly. If the name of P starts with -OLD-PREFIX, this is replaced by NEW-PREFIX; otherwise, NEW-PREFIX is -prepended to the name." - (let* ((rewrite-if-package - (lambda (content) - ;; CONTENT may be a file name, in which case it is returned, or a - ;; package, which is rewritten with the new PYTHON and NEW-PREFIX. - (if (package? content) - (package-with-explicit-python content python - old-prefix new-prefix) - content))) - (rewrite - (match-lambda - ((name content . rest) - (append (list name (rewrite-if-package content)) rest))))) - - (if (eq? (package-build-system p) python-build-system) - (package (inherit p) - (name (let ((name (package-name p))) - (string-append new-prefix - (if (string-prefix? old-prefix name) - (substring name (string-length old-prefix)) - name)))) - (arguments - (let ((arguments (package-arguments p)) - (python (if (promise? python) - (force python) - python))) - (if (member #:python arguments) - (substitute-keyword-arguments arguments ((#:python p) python)) - (append arguments `(#:python ,python))))) - (inputs (map rewrite (package-inputs p))) - (propagated-inputs (map rewrite (package-propagated-inputs p))) - (native-inputs (map rewrite (package-native-inputs p)))) - p))) +(define (package-with-explicit-python python old-prefix new-prefix) + "Return a procedure of one argument, P. The procedure creates a package with +the same fields as P, which is assumed to use PYTHON-BUILD-SYSTEM, such that +it is compiled with PYTHON instead. The inputs are changed recursively +accordingly. If the name of P starts with OLD-PREFIX, this is replaced by +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 + (lambda (content) + ;; CONTENT may be a file name, in which case it is returned, + ;; or a package, which is rewritten with the new PYTHON and + ;; NEW-PREFIX. + (if (package? content) + (transform content) + content))) + (rewrite + (match-lambda + ((name content . rest) + (append (list name (rewrite-if-package content)) rest))))) + + (if (eq? (package-build-system p) python-build-system) + (package + (inherit p) + (name (let ((name (package-name p))) + (string-append new-prefix + (if (string-prefix? old-prefix name) + (substring name + (string-length old-prefix)) + name)))) + (arguments + (let ((arguments (package-arguments p)) + (python (if (promise? python) + (force python) + python))) + (if (member #:python arguments) + (substitute-keyword-arguments arguments + ((#:python p) python)) + (append arguments `(#:python ,python))))) + (inputs (map rewrite (package-inputs p))) + (propagated-inputs (map rewrite (package-propagated-inputs p))) + (native-inputs (map rewrite (package-native-inputs p)))) + p))))) + + transform) (define package-with-python2 ;; Note: delay call to 'default-python2' until after the 'arguments' field ;; of packages is accessed to avoid a circular dependency when evaluating ;; the top-level of (gnu packages python). - (cut package-with-explicit-python <> (delay (default-python2)) - "python-" "python2-")) + (package-with-explicit-python (delay (default-python2)) + "python-" "python2-")) (define* (lower name #:key source inputs native-inputs outputs system target -- cgit v1.2.3