Commit | Line | Data |
---|---|---|
40506d5d | 1 | ;;; GNU Guix --- Functional package management for GNU |
f9704f17 | 2 | ;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org> |
11bb85a1 | 3 | ;;; Copyright © 2013 Andreas Enge <andreas@enge.fr> |
40506d5d NK |
4 | ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org> |
5 | ;;; | |
6 | ;;; This file is part of GNU Guix. | |
7 | ;;; | |
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. | |
12 | ;;; | |
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. | |
17 | ;;; | |
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/>. | |
20 | ||
21 | (define-module (guix build-system python) | |
22 | #:use-module (guix store) | |
23 | #:use-module (guix utils) | |
f9704f17 | 24 | #:use-module (guix memoization) |
40506d5d NK |
25 | #:use-module (guix packages) |
26 | #:use-module (guix derivations) | |
e89431bf | 27 | #:use-module (guix search-paths) |
40506d5d NK |
28 | #:use-module (guix build-system) |
29 | #:use-module (guix build-system gnu) | |
30 | #:use-module (ice-9 match) | |
1be83341 | 31 | #:use-module (srfi srfi-1) |
11bb85a1 | 32 | #:use-module (srfi srfi-26) |
bb42c78a LC |
33 | #:export (%python-build-system-modules |
34 | package-with-python2 | |
1be83341 | 35 | strip-python2-variant |
3c185b24 LC |
36 | default-python |
37 | default-python2 | |
11bb85a1 | 38 | python-build |
3009334e CR |
39 | python-build-system |
40 | pypi-uri)) | |
40506d5d NK |
41 | |
42 | ;; Commentary: | |
43 | ;; | |
44 | ;; Standard build procedure for Python packages using 'setup.py'. This is | |
45 | ;; implemented as an extension of 'gnu-build-system'. | |
46 | ;; | |
47 | ;; Code: | |
48 | ||
17ad0a27 | 49 | (define* (pypi-uri name version #:optional (extension ".tar.gz")) |
3009334e | 50 | "Return a URI string for the Python package hosted on the Python Package |
17ad0a27 LC |
51 | Index (PyPI) corresponding to NAME and VERSION. EXTENSION is the file name |
52 | extension, such as '.tar.gz'." | |
a5376200 | 53 | (string-append "https://files.pythonhosted.org/packages/source/" |
3009334e | 54 | (string-take name 1) "/" name "/" |
17ad0a27 | 55 | name "-" version extension)) |
3009334e | 56 | |
bb42c78a LC |
57 | (define %python-build-system-modules |
58 | ;; Build-side modules imported by default. | |
59 | `((guix build python-build-system) | |
60 | ,@%gnu-build-system-modules)) | |
61 | ||
5282181d LC |
62 | (define (default-python) |
63 | "Return the default Python package." | |
64 | ;; Lazily resolve the binding to avoid a circular dependency. | |
65 | (let ((python (resolve-interface '(gnu packages python)))) | |
3df47231 | 66 | (module-ref python 'python-wrapper))) |
5282181d | 67 | |
11bb85a1 AE |
68 | (define (default-python2) |
69 | "Return the default Python 2 package." | |
70 | (let ((python (resolve-interface '(gnu packages python)))) | |
71 | (module-ref python 'python-2))) | |
72 | ||
1be83341 LC |
73 | (define* (package-with-explicit-python python old-prefix new-prefix |
74 | #:key variant-property) | |
b3e2a5af LC |
75 | "Return a procedure of one argument, P. The procedure creates a package with |
76 | the same fields as P, which is assumed to use PYTHON-BUILD-SYSTEM, such that | |
77 | it is compiled with PYTHON instead. The inputs are changed recursively | |
78 | accordingly. If the name of P starts with OLD-PREFIX, this is replaced by | |
1be83341 LC |
79 | NEW-PREFIX; otherwise, NEW-PREFIX is prepended to the name. |
80 | ||
81 | When VARIANT-PROPERTY is present, it is used as a key to search for | |
82 | pre-defined variants of this transformation recorded in the 'properties' field | |
83 | of packages. The property value must be the promise of a package. This is a | |
84 | convenient way for package writers to force the transformation to use | |
85 | pre-defined variants." | |
1618006d LC |
86 | (define package-variant |
87 | (if variant-property | |
88 | (lambda (package) | |
89 | (assq-ref (package-properties package) | |
90 | variant-property)) | |
91 | (const #f))) | |
78a27453 | 92 | |
1618006d LC |
93 | (define (transform p) |
94 | (cond | |
95 | ;; If VARIANT-PROPERTY is present, use that. | |
96 | ((package-variant p) | |
97 | => force) | |
1be83341 | 98 | |
1618006d LC |
99 | ;; Otherwise build the new package object graph. |
100 | ((eq? (package-build-system p) python-build-system) | |
101 | (package | |
102 | (inherit p) | |
103 | (location (package-location p)) | |
104 | (name (let ((name (package-name p))) | |
105 | (string-append new-prefix | |
106 | (if (string-prefix? old-prefix name) | |
107 | (substring name | |
108 | (string-length old-prefix)) | |
109 | name)))) | |
110 | (arguments | |
111 | (let ((python (if (promise? python) | |
112 | (force python) | |
113 | python))) | |
114 | (ensure-keyword-arguments (package-arguments p) | |
115 | `(#:python ,python)))))) | |
116 | (else p))) | |
b3e2a5af | 117 | |
1618006d LC |
118 | (define (cut? p) |
119 | (or (not (eq? (package-build-system p) python-build-system)) | |
120 | (package-variant p))) | |
121 | ||
122 | (package-mapping transform cut?)) | |
11bb85a1 AE |
123 | |
124 | (define package-with-python2 | |
8c9653b3 LC |
125 | ;; Note: delay call to 'default-python2' until after the 'arguments' field |
126 | ;; of packages is accessed to avoid a circular dependency when evaluating | |
127 | ;; the top-level of (gnu packages python). | |
b3e2a5af | 128 | (package-with-explicit-python (delay (default-python2)) |
1be83341 LC |
129 | "python-" "python2-" |
130 | #:variant-property 'python2-variant)) | |
131 | ||
132 | (define (strip-python2-variant p) | |
133 | "Remove the 'python2-variant' property from P." | |
134 | (package | |
135 | (inherit p) | |
136 | (properties (alist-delete 'python2-variant (package-properties p))))) | |
11bb85a1 | 137 | |
0d5a559f | 138 | (define* (lower name |
d3d337d2 | 139 | #:key source inputs native-inputs outputs system target |
0d5a559f LC |
140 | (python (default-python)) |
141 | #:allow-other-keys | |
142 | #:rest arguments) | |
143 | "Return a bag for NAME." | |
144 | (define private-keywords | |
145 | '(#:source #:target #:python #:inputs #:native-inputs)) | |
146 | ||
147 | (and (not target) ;XXX: no cross-compilation | |
148 | (bag | |
149 | (name name) | |
d3d337d2 | 150 | (system system) |
0d5a559f LC |
151 | (host-inputs `(,@(if source |
152 | `(("source" ,source)) | |
153 | '()) | |
154 | ,@inputs | |
155 | ||
156 | ;; Keep the standard inputs of 'gnu-build-system'. | |
157 | ,@(standard-packages))) | |
158 | (build-inputs `(("python" ,python) | |
159 | ,@native-inputs)) | |
160 | (outputs outputs) | |
161 | (build python-build) | |
162 | (arguments (strip-keyword-arguments private-keywords arguments))))) | |
163 | ||
164 | (define* (python-build store name inputs | |
40506d5d | 165 | #:key |
40506d5d | 166 | (tests? #t) |
5dfd5b82 | 167 | (test-target "test") |
5f7565d1 | 168 | (use-setuptools? #t) |
40506d5d NK |
169 | (configure-flags ''()) |
170 | (phases '(@ (guix build python-build-system) | |
171 | %standard-phases)) | |
172 | (outputs '("out")) | |
173 | (search-paths '()) | |
174 | (system (%current-system)) | |
175 | (guile #f) | |
bb42c78a | 176 | (imported-modules %python-build-system-modules) |
40506d5d | 177 | (modules '((guix build python-build-system) |
40506d5d NK |
178 | (guix build utils)))) |
179 | "Build SOURCE using PYTHON, and with INPUTS. This assumes that SOURCE | |
180 | provides a 'setup.py' file as its build system." | |
40506d5d NK |
181 | (define builder |
182 | `(begin | |
183 | (use-modules ,@modules) | |
184 | (python-build #:name ,name | |
0d5a559f LC |
185 | #:source ,(match (assoc-ref inputs "source") |
186 | (((? derivation? source)) | |
187 | (derivation->output-path source)) | |
188 | ((source) | |
189 | source) | |
190 | (source | |
191 | source)) | |
40506d5d NK |
192 | #:configure-flags ,configure-flags |
193 | #:system ,system | |
5dfd5b82 | 194 | #:test-target ,test-target |
40506d5d | 195 | #:tests? ,tests? |
5f7565d1 | 196 | #:use-setuptools? ,use-setuptools? |
1d1f9397 | 197 | #:phases ,phases |
40506d5d | 198 | #:outputs %outputs |
40506d5d | 199 | #:search-paths ',(map search-path-specification->sexp |
0d5a559f | 200 | search-paths) |
40506d5d NK |
201 | #:inputs %build-inputs))) |
202 | ||
203 | (define guile-for-build | |
204 | (match guile | |
205 | ((? package?) | |
05962f29 | 206 | (package-derivation store guile system #:graft? #f)) |
40506d5d | 207 | (#f ; the default |
bdb36958 | 208 | (let* ((distro (resolve-interface '(gnu packages commencement))) |
40506d5d | 209 | (guile (module-ref distro 'guile-final))) |
05962f29 | 210 | (package-derivation store guile system #:graft? #f))))) |
40506d5d | 211 | |
0d5a559f LC |
212 | (build-expression->derivation store name builder |
213 | #:inputs inputs | |
214 | #:system system | |
215 | #:modules imported-modules | |
216 | #:outputs outputs | |
217 | #:guile-for-build guile-for-build)) | |
40506d5d NK |
218 | |
219 | (define python-build-system | |
0d5a559f LC |
220 | (build-system |
221 | (name 'python) | |
222 | (description "The standard Python build system") | |
223 | (lower lower))) | |
40506d5d NK |
224 | |
225 | ;;; python.scm ends here |