1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013, 2015 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2013 Andreas Enge <andreas@enge.fr>
4 ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
6 ;;; This file is part of GNU Guix.
8 ;;; GNU Guix is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
13 ;;; GNU Guix is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;;; GNU General Public License for more details.
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21 (define-module (guix build python-build-system)
22 #:use-module ((guix build gnu-build-system) #:prefix gnu:)
23 #:use-module (guix build utils)
24 #:use-module (ice-9 match)
25 #:use-module (ice-9 ftw)
26 #:use-module (srfi srfi-1)
27 #:use-module (srfi srfi-26)
28 #:export (%standard-phases
33 ;; Builder-side code of the standard Python package build procedure.
38 (define (call-setuppy command params)
39 (if (file-exists? "setup.py")
41 (format #t "running \"python setup.py\" with command ~s and parameters ~s~%"
43 (zero? (apply system* "python" "setup.py" command params)))
44 (error "no setup.py found")))
46 (define* (build #:rest empty)
47 "Build a given Python package."
48 (call-setuppy "build" '()))
50 (define* (check #:key tests? test-target #:allow-other-keys)
51 "Run the test suite of a given Python package."
53 (call-setuppy test-target '())
56 (define (get-python-version python)
57 (string-take (string-take-right python 5) 3))
59 (define* (install #:key outputs inputs (configure-flags '())
61 "Install a given Python package."
62 (let* ((out (assoc-ref outputs "out"))
63 (params (append (list (string-append "--prefix=" out))
65 (python-version (get-python-version (assoc-ref inputs "python")))
66 (old-path (getenv "PYTHONPATH"))
67 (add-path (string-append out "/lib/python" python-version
69 ;; create the module installation directory and add it to PYTHONPATH
70 ;; to make setuptools happy
73 (string-append (if old-path
74 (string-append old-path ":")
77 (call-setuppy "install" params)))
79 (define* (wrap #:key inputs outputs #:allow-other-keys)
80 (define (list-of-files dir)
81 (map (cut string-append dir "/" <>)
82 (or (scandir dir (lambda (f)
83 (let ((s (stat (string-append dir "/" f))))
84 (eq? 'regular (stat:type s)))))
88 (append-map (match-lambda
90 (list (string-append dir "/bin")
91 (string-append dir "/sbin"))))
94 (let* ((out (assoc-ref outputs "out"))
95 (python (assoc-ref inputs "python"))
96 (var `("PYTHONPATH" prefix
97 ,(cons (string-append out "/lib/python"
98 (get-python-version python)
100 (search-path-as-string->list
101 (or (getenv "PYTHONPATH") ""))))))
102 (for-each (lambda (dir)
103 (let ((files (list-of-files dir)))
104 (for-each (cut wrap-program <> var)
108 (define* (rename-pth-file #:key name inputs outputs #:allow-other-keys)
109 "Rename easy-install.pth to NAME.pth to avoid conflicts between packages
110 installed with setuptools."
111 (let* ((out (assoc-ref outputs "out"))
112 (python (assoc-ref inputs "python"))
113 (site-packages (string-append out "/lib/python"
114 (get-python-version python)
116 (easy-install-pth (string-append site-packages "/easy-install.pth"))
117 (new-pth (string-append site-packages "/" name ".pth")))
118 (when (file-exists? easy-install-pth)
119 (rename-file easy-install-pth new-pth))
122 (define %standard-phases
123 ;; 'configure' and 'build' phases are not needed. Everything is done during
125 (modify-phases gnu:%standard-phases
127 (replace 'install install)
128 (replace 'check check)
129 (replace 'build build)
130 (add-after 'install 'wrap wrap)
131 (add-before 'strip 'rename-pth-file rename-pth-file)))
133 (define* (python-build #:key inputs (phases %standard-phases)
134 #:allow-other-keys #:rest args)
135 "Build the given Python package, applying all of PHASES in order."
136 (apply gnu:gnu-build #:inputs inputs #:phases phases args))
138 ;;; python-build-system.scm ends here