1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
4 ;;; This file is part of GNU Guix.
6 ;;; GNU Guix is free software; you can redistribute it and/or modify it
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.
11 ;;; GNU Guix is distributed in the hope that it will be useful, but
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.
16 ;;; You should have received a copy of the GNU General Public License
17 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19 (define-module (guix build-system gnu)
20 #:use-module (guix store)
21 #:use-module (guix utils)
22 #:use-module (guix memoization)
23 #:use-module (guix derivations)
24 #:use-module (guix search-paths)
25 #:use-module (guix build-system)
26 #:use-module (guix packages)
27 #:use-module (srfi srfi-1)
28 #:use-module (ice-9 match)
29 #:export (%gnu-build-system-modules
33 standard-cross-packages
34 package-with-explicit-inputs
35 package-with-extra-configure-variable
39 package-with-restricted-references))
43 ;; Standard build procedure for packages using the GNU Build System or
44 ;; something compatible ("./configure && make && make install").
48 (define %gnu-build-system-modules
49 ;; Build-side modules imported and used by default.
50 '((guix build gnu-build-system)
55 (define %default-modules
56 ;; Modules in scope in the build-side environment.
57 '((guix build gnu-build-system)
60 (define* (package-with-explicit-inputs/deprecated p inputs
62 (loc (current-source-location))
63 #:key (native-inputs '())
65 "This variant is deprecated because it is inefficient: it memoizes only
66 temporarily instead of memoizing across all transformations where INPUTS is
69 Rewrite P, which is assumed to use GNU-BUILD-SYSTEM, to take INPUTS and
70 NATIVE-INPUTS as explicit inputs instead of the implicit default, and return
71 it. INPUTS and NATIVE-INPUTS can be either input lists or thunks; in the
72 latter case, they will be called in a context where the `%current-system' and
73 `%current-target-system' are suitably parametrized. Use GUILE to run the
74 builder, or the distro's final Guile when GUILE is #f."
75 (define inputs* inputs)
76 (define native-inputs* native-inputs)
79 (if (procedure? inputs)
83 (define (duplicate-filter inputs)
84 (let ((names (match (call inputs)
88 (fold alist-delete inputs names))))
91 (define rewritten-input
94 ((name (? package? p) sub-drv ...)
95 ;; XXX: Check whether P's build system knows #:implicit-inputs, for
96 ;; things like `cross-pkg-config'.
97 (if (eq? (package-build-system p) gnu-build-system)
98 (cons* name (loop p) sub-drv)
99 (cons* name p sub-drv)))
103 (location (if (pair? loc) (source-properties->location loc) loc))
105 ;; 'ensure-keyword-arguments' guarantees that this procedure is
107 (ensure-keyword-arguments (package-arguments p)
109 #:implicit-inputs? #f)))
111 (let ((replacement (package-replacement p)))
113 (package-with-explicit-inputs replacement inputs loc
118 (let ((filtered (duplicate-filter native-inputs*)))
119 `(,@(call native-inputs*)
120 ,@(map rewritten-input
121 (filtered (package-native-inputs p))))))
124 (package-propagated-inputs p)))
126 (let ((filtered (duplicate-filter inputs*)))
128 ,@(map rewritten-input
129 (filtered (package-inputs p)))))))))
131 (define* (package-with-explicit-inputs* inputs #:optional guile)
132 "Return a procedure that rewrites the given package and all its dependencies
133 so that they use INPUTS (a thunk) instead of implicit inputs."
134 (define (duplicate-filter package-inputs)
135 (let ((names (match (inputs)
138 (fold alist-delete package-inputs names)))
140 (define (add-explicit-inputs p)
141 (if (and (eq? (package-build-system p) gnu-build-system)
142 (not (memq #:implicit-inputs? (package-arguments p))))
145 (inputs (append (inputs)
146 (duplicate-filter (package-inputs p))))
148 (ensure-keyword-arguments (package-arguments p)
149 `(#:implicit-inputs? #f
154 (or (not (eq? (package-build-system p) gnu-build-system))
155 (memq #:implicit-inputs? (package-arguments p))))
157 (package-mapping add-explicit-inputs cut?))
159 (define package-with-explicit-inputs
161 ((inputs #:optional guile)
162 (package-with-explicit-inputs* inputs guile))
163 ((p inputs #:optional (loc (current-source-location))
164 #:key (native-inputs '()) guile)
166 (package-with-explicit-inputs/deprecated p inputs
172 (define (package-with-extra-configure-variable p variable value)
173 "Return a version of P with VARIABLE=VALUE specified as an extra `configure'
174 flag, recursively. An example is LDFLAGS=-static. If P already has configure
175 flags for VARIABLE, the associated value is augmented."
177 (define (rewritten-inputs inputs)
179 ((name (? package? p) sub ...)
180 `(,name ,(loop p) ,@sub))
186 (let ((args (package-arguments p)))
187 (substitute-keyword-arguments args
188 ((#:configure-flags flags)
189 (let* ((var= (string-append variable "="))
190 (len (string-length var=)))
191 `(cons ,(string-append var= value)
193 (if (string-prefix? ,var= flag)
195 ,(string-append var= value " ")
196 (substring flag ,len))
200 (let ((replacement (package-replacement p)))
202 (package-with-extra-configure-variable replacement
204 (inputs (rewritten-inputs (package-inputs p)))
205 (propagated-inputs (rewritten-inputs (package-propagated-inputs p))))))
207 (define (static-libgcc-package p)
208 "A version of P linked with `-static-gcc'."
209 (package-with-extra-configure-variable p "LDFLAGS" "-static-libgcc"))
211 (define* (static-package p #:key (strip-all? #t))
212 "Return a statically-linked version of package P. If STRIP-ALL? is true,
213 use `--strip-all' as the arguments to `strip'."
216 (let ((a (default-keyword-arguments (package-arguments p)
217 '(#:configure-flags '()
218 #:strip-flags '("--strip-debug")))))
219 (substitute-keyword-arguments a
220 ((#:configure-flags flags)
221 `(cons* "--disable-shared" "LDFLAGS=-static" ,flags))
222 ((#:strip-flags flags)
226 (replacement (and=> (package-replacement p) static-package))))
228 (define* (dist-package p source #:key (phases '%dist-phases))
229 "Return a package that runs takes source files from the SOURCE directory,
230 runs `make distcheck' and whose result is one or more source tarballs. The
231 exact build phases are defined by PHASES."
234 (name (string-append (package-name p) "-dist"))
237 ;; Use the right phases and modules.
238 (let* ((args (default-keyword-arguments (package-arguments p)
240 #:modules ,%default-modules
241 #:imported-modules ,%gnu-build-system-modules))))
242 (substitute-keyword-arguments args
244 `((guix build gnu-dist)
246 ((#:imported-modules modules)
247 `((guix build gnu-dist)
252 ;; Add autotools & co. as inputs.
253 (let ((ref (lambda (module var)
254 (module-ref (resolve-interface module) var))))
255 `(,@(package-native-inputs p)
256 ("autoconf" ,((ref '(gnu packages autotools) 'autoconf-wrapper)))
257 ("automake" ,(ref '(gnu packages autotools) 'automake))
258 ("libtool" ,(ref '(gnu packages autotools) 'libtool))
259 ("gettext" ,(ref '(gnu packages gettext) 'gnu-gettext))
260 ("texinfo" ,(ref '(gnu packages texinfo) 'texinfo))))))))
262 (define (package-with-restricted-references p refs)
263 "Return a package whose outputs are guaranteed to only refer to the packages
265 (if (eq? (package-build-system p) gnu-build-system) ; XXX: dirty
267 (arguments `(#:allowed-references ,refs
268 ,@(package-arguments p))))
272 (define (standard-packages)
273 "Return the list of (NAME PACKAGE OUTPUT) or (NAME PACKAGE) tuples of
274 standard packages used as implicit inputs of the GNU build system."
276 ;; Resolve (gnu packages commencement) lazily to hide circular dependency.
277 (let ((distro (resolve-module '(gnu packages commencement))))
278 (module-ref distro '%final-inputs)))
281 #:key source inputs native-inputs outputs target
282 (implicit-inputs? #t) (implicit-cross-inputs? #t)
283 (strip-binaries? #t) system
286 "Return a bag for NAME from the given arguments."
287 (define private-keywords
288 `(#:source #:inputs #:native-inputs #:outputs
289 #:implicit-inputs? #:implicit-cross-inputs?
290 ,@(if target '() '(#:target))))
294 (system system) (target target)
295 (build-inputs `(,@(if source
296 `(("source" ,source))
300 ;; When not cross-compiling, ensure implicit inputs come
301 ;; last. That way, libc headers come last, which allows
302 ;; #include_next to work correctly; see
303 ;; <https://bugs.gnu.org/30756>.
304 ,@(if target '() inputs)
305 ,@(if (and target implicit-cross-inputs?)
306 (standard-cross-packages target 'host)
308 ,@(if implicit-inputs?
311 (host-inputs (if target inputs '()))
313 ;; The cross-libc is really a target package, but for bootstrapping
314 ;; reasons, we can't put it in 'host-inputs'. Namely, 'cross-gcc' is a
315 ;; native package, so it would end up using a "native" variant of
316 ;; 'cross-libc' (built with 'gnu-build'), whereas all the other packages
317 ;; would use a target variant (built with 'gnu-cross-build'.)
318 (target-inputs (if (and target implicit-cross-inputs?)
319 (standard-cross-packages target 'target)
321 (outputs (if strip-binaries?
323 (delete "debug" outputs)))
324 (build (if target gnu-cross-build gnu-build))
325 (arguments (strip-keyword-arguments private-keywords arguments))))
327 (define %license-file-regexp
328 ;; Regexp matching license files.
329 "^(COPYING.*|LICEN[CS]E.*|[Ll]icen[cs]e.*|Copy[Rr]ight(\\.(txt|md))?)$")
331 (define* (gnu-build store name input-drvs
335 (configure-flags ''())
339 (test-target "check")
344 (strip-flags ''("--strip-debug"
345 "--enable-deterministic-archives"))
346 (strip-directories ''("lib" "lib64" "libexec"
348 (validate-runpath? #t)
349 (license-file-regexp %license-file-regexp)
350 (phases '%standard-phases)
351 (locale "en_US.utf8")
352 (system (%current-system))
353 (build (nix-system->gnu-triplet system))
354 (imported-modules %gnu-build-system-modules)
355 (modules %default-modules)
358 disallowed-references)
359 "Return a derivation called NAME that builds from tarball SOURCE, with
360 input derivation INPUTS, using the usual procedure of the GNU Build
361 System. The builder is run with GUILE, or with the distro's final Guile
362 package if GUILE is #f or omitted.
364 The builder is run in a context where MODULES are used; IMPORTED-MODULES
365 specifies modules not provided by Guile itself that must be imported in
366 the builder's environment, from the host. Note that we distinguish
367 between both, because for Guile's own modules like (ice-9 foo), we want
368 to use GUILE's own version of it, rather than import the user's one,
369 which could lead to gratuitous input divergence.
371 SUBSTITUTABLE? determines whether users may be able to use substitutes of the
372 returned derivations, or whether they should always build it locally.
374 ALLOWED-REFERENCES can be either #f, or a list of packages that the outputs
375 are allowed to refer to. Likewise for DISALLOWED-REFERENCES, which lists
376 packages that must not be referenced."
377 (define canonicalize-reference
380 (derivation->output-path (package-derivation store p system
382 (((? package? p) output)
383 (derivation->output-path (package-derivation store p system
391 (use-modules ,@modules)
392 (gnu-build #:source ,(match (assoc-ref input-drvs "source")
393 (((? derivation? source))
394 (derivation->output-path source))
402 #:inputs %build-inputs
403 #:search-paths ',(map search-path-specification->sexp
407 #:configure-flags ,configure-flags
408 #:make-flags ,make-flags
409 #:out-of-source? ,out-of-source?
411 #:test-target ,test-target
412 #:parallel-build? ,parallel-build?
413 #:parallel-tests? ,parallel-tests?
414 #:patch-shebangs? ,patch-shebangs?
415 #:strip-binaries? ,strip-binaries?
416 #:validate-runpath? ,validate-runpath?
417 #:license-file-regexp ,license-file-regexp
418 #:strip-flags ,strip-flags
419 #:strip-directories ,strip-directories)))
421 (define guile-for-build
424 (package-derivation store guile system #:graft? #f))
426 (let* ((distro (resolve-interface '(gnu packages commencement)))
427 (guile (module-ref distro 'guile-final)))
428 (package-derivation store guile system
431 (build-expression->derivation store name builder
435 #:modules imported-modules
436 #:substitutable? substitutable?
439 (and allowed-references
440 (map canonicalize-reference
442 #:disallowed-references
443 (and disallowed-references
444 (map canonicalize-reference
445 disallowed-references))
446 #:guile-for-build guile-for-build))
450 ;;; Cross-compilation.
453 (define standard-cross-packages
454 (mlambda (target kind)
455 "Return the list of name/package tuples to cross-build for TARGET. KIND
456 is one of `host' or `target'."
457 (let* ((cross (resolve-interface '(gnu packages cross-base)))
458 (gcc (module-ref cross 'cross-gcc))
459 (binutils (module-ref cross 'cross-binutils))
460 (libc (module-ref cross 'cross-libc)))
463 ;; Cross-GCC appears once here, so that it's in $PATH...
464 `(("cross-gcc" ,(gcc target
465 #:xbinutils (binutils target)
466 #:libc (libc target)))
467 ("cross-binutils" ,(binutils target))))
469 (let ((libc (libc target)))
470 ;; ... and once here, so that libstdc++ & co. are in
471 ;; CROSS_CPLUS_INCLUDE_PATH, etc.
472 `(("cross-gcc" ,(gcc target
473 #:xbinutils (binutils target)
477 ;; MinGW's libc doesn't have a "static" output.
478 ,@(if (member "static" (package-outputs libc))
479 `(("cross-libc:static" ,libc "static"))
482 (define* (gnu-cross-build store name
484 target native-drvs target-drvs
489 (native-search-paths '())
491 (configure-flags ''())
494 (tests? #f) ; nothing can be done
495 (test-target "check")
496 (parallel-build? #t) (parallel-tests? #t)
499 (strip-flags ''("--strip-debug"
500 "--enable-deterministic-archives"))
501 (strip-directories ''("lib" "lib64" "libexec"
503 (validate-runpath? #t)
504 (license-file-regexp %license-file-regexp)
505 (phases '%standard-phases)
506 (locale "en_US.utf8")
507 (system (%current-system))
508 (build (nix-system->gnu-triplet system))
509 (imported-modules %gnu-build-system-modules)
510 (modules %default-modules)
513 disallowed-references)
514 "Cross-build NAME for TARGET, where TARGET is a GNU triplet. INPUTS are
515 cross-built inputs, and NATIVE-INPUTS are inputs that run on the build
517 (define canonicalize-reference
520 (derivation->output-path (package-cross-derivation store p system)))
521 (((? package? p) output)
522 (derivation->output-path (package-cross-derivation store p system)
529 (use-modules ,@modules)
532 (define %build-host-inputs
534 ((name (? derivation? drv) sub ...)
535 `(,name . ,(apply derivation->output-path drv sub)))
540 (define %build-target-inputs
542 ((name (? derivation? drv) sub ...)
543 `(,name . ,(apply derivation->output-path drv sub)))
544 ((name (? package? pkg) sub ...)
545 (let ((drv (package-cross-derivation store pkg
547 `(,name . ,(apply derivation->output-path drv sub))))
552 (gnu-build #:source ,(match (assoc-ref native-drvs "source")
553 (((? derivation? source))
554 (derivation->output-path source))
563 #:inputs %build-target-inputs
564 #:native-inputs %build-host-inputs
565 #:search-paths ',(map search-path-specification->sexp
567 #:native-search-paths ',(map
568 search-path-specification->sexp
572 #:configure-flags ,configure-flags
573 #:make-flags ,make-flags
574 #:out-of-source? ,out-of-source?
576 #:test-target ,test-target
577 #:parallel-build? ,parallel-build?
578 #:parallel-tests? ,parallel-tests?
579 #:patch-shebangs? ,patch-shebangs?
580 #:strip-binaries? ,strip-binaries?
581 #:validate-runpath? ,validate-runpath?
582 #:license-file-regexp ,license-file-regexp
583 #:strip-flags ,strip-flags
584 #:strip-directories ,strip-directories))))
586 (define guile-for-build
589 (package-derivation store guile system #:graft? #f))
591 (let* ((distro (resolve-interface '(gnu packages commencement)))
592 (guile (module-ref distro 'guile-final)))
593 (package-derivation store guile system #:graft? #f)))))
595 (build-expression->derivation store name builder
597 #:inputs (append native-drvs target-drvs)
599 #:modules imported-modules
600 #:substitutable? substitutable?
603 (and allowed-references
604 (map canonicalize-reference
606 #:disallowed-references
607 (and disallowed-references
608 (map canonicalize-reference
609 disallowed-references))
610 #:guile-for-build guile-for-build))
612 (define gnu-build-system
616 "The GNU Build System—i.e., ./configure && make && make install")