build-system: Use 'modify-phases'.
[jackhill/guix/guix.git] / guix / build-system / gnu.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
b15d79df 2;;; Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
c36db98c 3;;;
233e7676 4;;; This file is part of GNU Guix.
c36db98c 5;;;
233e7676 6;;; GNU Guix is free software; you can redistribute it and/or modify it
c36db98c
LC
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
233e7676 11;;; GNU Guix is distributed in the hope that it will be useful, but
c36db98c
LC
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
233e7676 17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
c36db98c 18
208f7cd1 19(define-module (guix build-system gnu)
c36db98c
LC
20 #:use-module (guix store)
21 #:use-module (guix utils)
22 #:use-module (guix derivations)
208f7cd1 23 #:use-module (guix build-system)
60f984b2 24 #:use-module (guix packages)
c36db98c 25 #:use-module (srfi srfi-1)
60f984b2 26 #:use-module (ice-9 match)
208f7cd1 27 #:export (gnu-build
60f984b2 28 gnu-build-system
0d5a559f 29 standard-packages
53dcd5ee
LC
30 package-with-explicit-inputs
31 package-with-extra-configure-variable
4d058c67 32 static-libgcc-package
fe12c345 33 static-package
f986c264
LC
34 dist-package
35 package-with-restricted-references))
c36db98c
LC
36
37;; Commentary:
38;;
39;; Standard build procedure for packages using the GNU Build System or
40;; something compatible ("./configure && make && make install").
41;;
42;; Code:
43
fe12c345
LC
44(define %default-modules
45 ;; Build-side modules imported and used by default.
46 '((guix build gnu-build-system)
47 (guix build utils)))
48
7e873a67 49(define* (package-with-explicit-inputs p inputs
60f984b2 50 #:optional
12d5aa0f 51 (loc (current-source-location))
7e873a67
LC
52 #:key (native-inputs '())
53 guile)
54 "Rewrite P, which is assumed to use GNU-BUILD-SYSTEM, to take INPUTS and
55NATIVE-INPUTS as explicit inputs instead of the implicit default, and return
56it. INPUTS and NATIVE-INPUTS can be either input lists or thunks; in the
57latter case, they will be called in a context where the `%current-system' and
58`%current-target-system' are suitably parametrized. Use GUILE to run the
59builder, or the distro's final Guile when GUILE is #f."
60 (define inputs* inputs)
61 (define native-inputs* native-inputs)
60f984b2 62
7e873a67
LC
63 (define (call inputs)
64 (if (procedure? inputs)
65 (inputs)
66 inputs))
60f984b2 67
7e873a67
LC
68 (define (duplicate-filter inputs)
69 (let ((names (match (call inputs)
70 (((name _ ...) ...)
71 name))))
72 (lambda (inputs)
73 (fold alist-delete inputs names))))
60f984b2 74
7e873a67
LC
75 (let loop ((p p))
76 (define rewritten-input
77 (memoize
78 (match-lambda
79 ((name (? package? p) sub-drv ...)
a3cff41d
LC
80 ;; XXX: Check whether P's build system knows #:implicit-inputs, for
81 ;; things like `cross-pkg-config'.
82 (if (eq? (package-build-system p) gnu-build-system)
83 (cons* name (loop p) sub-drv)
84 (cons* name p sub-drv)))
7e873a67
LC
85 (x x))))
86
87 (package (inherit p)
88 (location (if (pair? loc) (source-properties->location loc) loc))
89 (arguments
90 (let ((args (package-arguments p)))
91 `(#:guile ,guile
92 #:implicit-inputs? #f
93 ,@args)))
05962f29
LC
94 (replacement
95 (let ((replacement (package-replacement p)))
96 (and replacement
97 (package-with-explicit-inputs replacement inputs loc
98 #:native-inputs
99 native-inputs
100 #:guile guile))))
7e873a67
LC
101 (native-inputs
102 (let ((filtered (duplicate-filter native-inputs*)))
103 `(,@(call native-inputs*)
104 ,@(map rewritten-input
105 (filtered (package-native-inputs p))))))
106 (propagated-inputs
107 (map rewritten-input
108 (package-propagated-inputs p)))
109 (inputs
110 (let ((filtered (duplicate-filter inputs*)))
111 `(,@(call inputs*)
112 ,@(map rewritten-input
113 (filtered (package-inputs p)))))))))
60f984b2 114
53dcd5ee 115(define (package-with-extra-configure-variable p variable value)
a38f0ab0
LC
116 "Return a version of P with VARIABLE=VALUE specified as an extra `configure'
117flag, recursively. An example is LDFLAGS=-static. If P already has configure
118flags for VARIABLE, the associated value is augmented."
53dcd5ee
LC
119 (let loop ((p p))
120 (define (rewritten-inputs inputs)
121 (map (match-lambda
122 ((name (? package? p) sub ...)
123 `(,name ,(loop p) ,@sub))
124 (input input))
125 inputs))
126
127 (package (inherit p)
128 (arguments
21c203a5
LC
129 (let ((args (package-arguments p)))
130 (substitute-keyword-arguments args
131 ((#:configure-flags flags)
132 (let* ((var= (string-append variable "="))
133 (len (string-length var=)))
134 `(cons ,(string-append var= value)
135 (map (lambda (flag)
136 (if (string-prefix? ,var= flag)
137 (string-append
138 ,(string-append var= value " ")
139 (substring flag ,len))
140 flag))
141 ,flags)))))))
05962f29
LC
142 (replacement
143 (let ((replacement (package-replacement p)))
144 (and replacement
145 (package-with-extra-configure-variable replacement
146 variable value))))
53dcd5ee
LC
147 (inputs (rewritten-inputs (package-inputs p)))
148 (propagated-inputs (rewritten-inputs (package-propagated-inputs p))))))
149
150(define (static-libgcc-package p)
151 "A version of P linked with `-static-gcc'."
152 (package-with-extra-configure-variable p "LDFLAGS" "-static-libgcc"))
153
9011e97f
LC
154(define* (static-package p #:optional (loc (current-source-location))
155 #:key (strip-all? #t))
156 "Return a statically-linked version of package P. If STRIP-ALL? is true,
157use `--strip-all' as the arguments to `strip'."
a3e69bb8
LC
158 (package (inherit p)
159 (location (source-properties->location loc))
160 (arguments
161 (let ((a (default-keyword-arguments (package-arguments p)
162 '(#:configure-flags '()
163 #:strip-flags '("--strip-debug")))))
164 (substitute-keyword-arguments a
165 ((#:configure-flags flags)
166 `(cons* "--disable-shared" "LDFLAGS=-static" ,flags))
167 ((#:strip-flags flags)
168 (if strip-all?
169 ''("--strip-all")
05962f29
LC
170 flags)))))
171 (replacement (and=> (package-replacement p) static-package))))
4d058c67 172
fe12c345
LC
173(define* (dist-package p source)
174 "Return a package that runs takes source files from the SOURCE directory,
175runs `make distcheck' and whose result is one or more source tarballs."
176 (let ((s source))
177 (package (inherit p)
178 (name (string-append (package-name p) "-dist"))
179 (source s)
180 (arguments
181 ;; Use the right phases and modules.
182 (let* ((args (default-keyword-arguments (package-arguments p)
183 `(#:phases #f
184 #:modules ,%default-modules
185 #:imported-modules ,%default-modules))))
186 (substitute-keyword-arguments args
187 ((#:modules modules)
188 `((guix build gnu-dist)
189 ,@modules))
190 ((#:imported-modules modules)
191 `((guix build gnu-dist)
192 ,@modules))
193 ((#:phases _)
194 '%dist-phases))))
195 (native-inputs
196 ;; Add autotools & co. as inputs.
197 (let ((ref (lambda (module var)
198 (module-ref (resolve-interface module) var))))
199 `(("autoconf" ,(ref '(gnu packages autotools) 'autoconf))
200 ("automake" ,(ref '(gnu packages autotools) 'automake))
201 ("libtool" ,(ref '(gnu packages autotools) 'libtool) "bin")
f4badde3 202 ("gettext" ,(ref '(gnu packages gettext) 'gnu-gettext))
fe12c345
LC
203 ("texinfo" ,(ref '(gnu packages texinfo) 'texinfo))))))))
204
f986c264
LC
205(define (package-with-restricted-references p refs)
206 "Return a package whose outputs are guaranteed to only refer to the packages
207listed in REFS."
208 (if (eq? (package-build-system p) gnu-build-system) ; XXX: dirty
209 (package (inherit p)
210 (arguments `(#:allowed-references ,refs
211 ,@(package-arguments p))))
212 p))
213
53dcd5ee 214\f
068cdcd0
LC
215(define (standard-packages)
216 "Return the list of (NAME PACKAGE OUTPUT) or (NAME PACKAGE) tuples of
217standard packages used as implicit inputs of the GNU build system."
218
bdb36958
LC
219 ;; Resolve (gnu packages commencement) lazily to hide circular dependency.
220 (let ((distro (resolve-module '(gnu packages commencement))))
068cdcd0
LC
221 (module-ref distro '%final-inputs)))
222
0d5a559f
LC
223(define* (lower name
224 #:key source inputs native-inputs outputs target
225 (implicit-inputs? #t) (implicit-cross-inputs? #t)
d3d337d2 226 (strip-binaries? #t) system
0d5a559f
LC
227 #:allow-other-keys
228 #:rest arguments)
229 "Return a bag for NAME from the given arguments."
230 (define private-keywords
231 `(#:source #:inputs #:native-inputs #:outputs
232 #:implicit-inputs? #:implicit-cross-inputs?
233 ,@(if target '() '(#:target))))
234
235 (bag
236 (name name)
d3d337d2 237 (system system) (target target)
0d5a559f
LC
238 (build-inputs `(,@(if source
239 `(("source" ,source))
240 '())
241 ,@native-inputs
242 ,@(if (and target implicit-cross-inputs?)
243 (standard-cross-packages target 'host)
244 '())
245 ,@(if implicit-inputs?
246 (standard-packages)
247 '())))
248 (host-inputs inputs)
249
250 ;; The cross-libc is really a target package, but for bootstrapping
251 ;; reasons, we can't put it in 'host-inputs'. Namely, 'cross-gcc' is a
252 ;; native package, so it would end up using a "native" variant of
253 ;; 'cross-libc' (built with 'gnu-build'), whereas all the other packages
254 ;; would use a target variant (built with 'gnu-cross-build'.)
255 (target-inputs (if (and target implicit-cross-inputs?)
256 (standard-cross-packages target 'target)
257 '()))
258 (outputs (if strip-binaries?
259 outputs
260 (delete "debug" outputs)))
261 (build (if target gnu-cross-build gnu-build))
262 (arguments (strip-keyword-arguments private-keywords arguments))))
263
264(define* (gnu-build store name input-drvs
12d5aa0f 265 #:key (guile #f)
a18eda27
LC
266 (outputs '("out"))
267 (search-paths '())
268 (configure-flags ''())
74cd03b1 269 (make-flags ''())
22b5d9c9 270 (out-of-source? #f)
c3c7eb41 271 (tests? #t)
6253961d 272 (test-target "check")
384de552
AE
273 (parallel-build? #t)
274 (parallel-tests? #t)
437fd809 275 (patch-shebangs? #t)
e815763e
LC
276 (strip-binaries? #t)
277 (strip-flags ''("--strip-debug"))
278 (strip-directories ''("lib" "lib64" "libexec"
279 "bin" "sbin"))
74cd03b1 280 (phases '%standard-phases)
3e43c64a 281 (system (%current-system))
fe12c345 282 (imported-modules %default-modules)
b15d79df 283 (modules %default-modules)
77b0ac90 284 (substitutable? #t)
b15d79df 285 allowed-references)
c36db98c 286 "Return a derivation called NAME that builds from tarball SOURCE, with
12d5aa0f
LC
287input derivation INPUTS, using the usual procedure of the GNU Build
288System. The builder is run with GUILE, or with the distro's final Guile
111111d0
LC
289package if GUILE is #f or omitted.
290
291The builder is run in a context where MODULES are used; IMPORTED-MODULES
292specifies modules not provided by Guile itself that must be imported in
293the builder's environment, from the host. Note that we distinguish
294between both, because for Guile's own modules like (ice-9 foo), we want
295to use GUILE's own version of it, rather than import the user's one,
b15d79df
LC
296which could lead to gratuitous input divergence.
297
77b0ac90
LC
298SUBSTITUTABLE? determines whether users may be able to use substitutes of the
299returned derivations, or whether they should always build it locally.
300
b15d79df
LC
301ALLOWED-REFERENCES can be either #f, or a list of packages that the outputs
302are allowed to refer to."
b15d79df
LC
303 (define canonicalize-reference
304 (match-lambda
305 ((? package? p)
05962f29
LC
306 (derivation->output-path (package-derivation store p system
307 #:graft? #f)))
b15d79df 308 (((? package? p) output)
05962f29
LC
309 (derivation->output-path (package-derivation store p system
310 #:graft? #f)
b15d79df
LC
311 output))
312 ((? string? output)
313 output)))
314
c36db98c
LC
315 (define builder
316 `(begin
3e43c64a 317 (use-modules ,@modules)
0d5a559f
LC
318 (gnu-build #:source ,(match (assoc-ref input-drvs "source")
319 (((? derivation? source))
320 (derivation->output-path source))
321 ((source)
322 source)
323 (source
324 source))
7172116c 325 #:system ,system
5dcfdcaa
LC
326 #:outputs %outputs
327 #:inputs %build-inputs
a18eda27 328 #:search-paths ',(map search-path-specification->sexp
0d5a559f 329 search-paths)
5dcfdcaa 330 #:phases ,phases
e1e8874e 331 #:configure-flags ,configure-flags
febaa885 332 #:make-flags ,make-flags
22b5d9c9 333 #:out-of-source? ,out-of-source?
c3c7eb41 334 #:tests? ,tests?
6253961d 335 #:test-target ,test-target
febaa885 336 #:parallel-build? ,parallel-build?
437fd809 337 #:parallel-tests? ,parallel-tests?
e815763e
LC
338 #:patch-shebangs? ,patch-shebangs?
339 #:strip-binaries? ,strip-binaries?
340 #:strip-flags ,strip-flags
341 #:strip-directories ,strip-directories)))
c36db98c 342
12d5aa0f
LC
343 (define guile-for-build
344 (match guile
81c7948d 345 ((? package?)
05962f29 346 (package-derivation store guile system #:graft? #f))
12d5aa0f 347 (#f ; the default
bdb36958 348 (let* ((distro (resolve-interface '(gnu packages commencement)))
12d5aa0f 349 (guile (module-ref distro 'guile-final)))
05962f29
LC
350 (package-derivation store guile system
351 #:graft? #f)))))
12d5aa0f 352
dd1a5a15
LC
353 (build-expression->derivation store name builder
354 #:system system
0d5a559f
LC
355 #:inputs input-drvs
356 #:outputs outputs
111111d0 357 #:modules imported-modules
77b0ac90
LC
358
359 ;; XXX: Update when
360 ;; <http://bugs.gnu.org/18747> is fixed.
361 #:local-build? (not substitutable?)
362
b15d79df
LC
363 #:allowed-references
364 (and allowed-references
365 (map canonicalize-reference
366 allowed-references))
12d5aa0f 367 #:guile-for-build guile-for-build))
208f7cd1 368
264218a4
LC
369\f
370;;;
371;;; Cross-compilation.
372;;;
373
374(define standard-cross-packages
375 (memoize
376 (lambda (target kind)
377 "Return the list of name/package tuples to cross-build for TARGET. KIND
378is one of `host' or `target'."
379 (let* ((cross (resolve-interface '(gnu packages cross-base)))
380 (gcc (module-ref cross 'cross-gcc))
381 (binutils (module-ref cross 'cross-binutils))
382 (libc (module-ref cross 'cross-libc)))
383 (case kind
384 ((host)
385 `(("cross-gcc" ,(gcc target
386 (binutils target)
387 (libc target)))
0d5a559f 388 ("cross-binutils" ,(binutils target))))
264218a4
LC
389 ((target)
390 `(("cross-libc" ,(libc target)))))))))
391
0d5a559f 392(define* (gnu-cross-build store name
264218a4 393 #:key
0d5a559f 394 target native-drvs target-drvs
264218a4 395 (guile #f)
0d5a559f 396 source
264218a4
LC
397 (outputs '("out"))
398 (search-paths '())
399 (native-search-paths '())
400
401 (configure-flags ''())
402 (make-flags ''())
264218a4 403 (out-of-source? #f)
f7c34290 404 (tests? #f) ; nothing can be done
264218a4
LC
405 (test-target "check")
406 (parallel-build? #t) (parallel-tests? #t)
407 (patch-shebangs? #t)
408 (strip-binaries? #t)
409 (strip-flags ''("--strip-debug"))
410 (strip-directories ''("lib" "lib64" "libexec"
411 "bin" "sbin"))
56c092ce 412 (phases '%standard-phases)
264218a4 413 (system (%current-system))
264218a4 414 (imported-modules '((guix build gnu-build-system)
264218a4
LC
415 (guix build utils)))
416 (modules '((guix build gnu-build-system)
b15d79df 417 (guix build utils)))
77b0ac90 418 (substitutable? #t)
b15d79df 419 allowed-references)
264218a4
LC
420 "Cross-build NAME for TARGET, where TARGET is a GNU triplet. INPUTS are
421cross-built inputs, and NATIVE-INPUTS are inputs that run on the build
422platform."
b15d79df
LC
423 (define canonicalize-reference
424 (match-lambda
425 ((? package? p)
426 (derivation->output-path (package-cross-derivation store p system)))
427 (((? package? p) output)
428 (derivation->output-path (package-cross-derivation store p system)
429 output))
430 ((? string? output)
431 output)))
432
264218a4
LC
433 (define builder
434 `(begin
435 (use-modules ,@modules)
436
437 (let ()
438 (define %build-host-inputs
439 ',(map (match-lambda
59688fc4
LC
440 ((name (? derivation? drv) sub ...)
441 `(,name . ,(apply derivation->output-path drv sub)))
ee4d7368
LC
442 ((name path)
443 `(,name . ,path)))
0d5a559f 444 native-drvs))
264218a4
LC
445
446 (define %build-target-inputs
447 ',(map (match-lambda
59688fc4
LC
448 ((name (? derivation? drv) sub ...)
449 `(,name . ,(apply derivation->output-path drv sub)))
0d5a559f
LC
450 ((name (? package? pkg) sub ...)
451 (let ((drv (package-cross-derivation store pkg
452 target system)))
453 `(,name . ,(apply derivation->output-path drv sub))))
ee4d7368
LC
454 ((name path)
455 `(,name . ,path)))
0d5a559f
LC
456 target-drvs))
457
458 (gnu-build #:source ,(match (assoc-ref native-drvs "source")
459 (((? derivation? source))
460 (derivation->output-path source))
461 ((source)
462 source)
463 (source
464 source))
264218a4
LC
465 #:system ,system
466 #:target ,target
467 #:outputs %outputs
468 #:inputs %build-target-inputs
469 #:native-inputs %build-host-inputs
470 #:search-paths ',(map search-path-specification->sexp
0d5a559f 471 search-paths)
264218a4
LC
472 #:native-search-paths ',(map
473 search-path-specification->sexp
0d5a559f 474 native-search-paths)
264218a4
LC
475 #:phases ,phases
476 #:configure-flags ,configure-flags
477 #:make-flags ,make-flags
478 #:out-of-source? ,out-of-source?
479 #:tests? ,tests?
480 #:test-target ,test-target
481 #:parallel-build? ,parallel-build?
482 #:parallel-tests? ,parallel-tests?
483 #:patch-shebangs? ,patch-shebangs?
484 #:strip-binaries? ,strip-binaries?
485 #:strip-flags ,strip-flags
486 #:strip-directories ,strip-directories))))
487
488 (define guile-for-build
489 (match guile
490 ((? package?)
05962f29 491 (package-derivation store guile system #:graft? #f))
264218a4 492 (#f ; the default
bdb36958 493 (let* ((distro (resolve-interface '(gnu packages commencement)))
264218a4 494 (guile (module-ref distro 'guile-final)))
05962f29 495 (package-derivation store guile system #:graft? #f)))))
264218a4 496
dd1a5a15
LC
497 (build-expression->derivation store name builder
498 #:system system
0d5a559f
LC
499 #:inputs (append native-drvs target-drvs)
500 #:outputs outputs
264218a4 501 #:modules imported-modules
77b0ac90
LC
502
503 ;; XXX: Update when
504 ;; <http://bugs.gnu.org/18747> is fixed.
505 #:local-build? (not substitutable?)
506
b15d79df
LC
507 #:allowed-references
508 (and allowed-references
509 (map canonicalize-reference
510 allowed-references))
264218a4
LC
511 #:guile-for-build guile-for-build))
512
208f7cd1 513(define gnu-build-system
0d5a559f
LC
514 (build-system
515 (name 'gnu)
516 (description
517 "The GNU Build System—i.e., ./configure && make && make install")
518 (lower lower)))