1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2012, 2013, 2014 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 (gnu packages make-bootstrap)
20 #:use-module (guix utils)
21 #:use-module (guix packages)
22 #:use-module (guix licenses)
23 #:use-module (guix build-system trivial)
24 #:use-module (guix build-system gnu)
25 #:use-module ((gnu packages) #:select (search-patch))
26 #:use-module ((gnu packages commencement) #:select (%final-inputs))
27 #:use-module (gnu packages base)
28 #:use-module (gnu packages cross-base)
29 #:use-module (gnu packages bash)
30 #:use-module (gnu packages compression)
31 #:use-module (gnu packages gawk)
32 #:use-module (gnu packages gcc)
33 #:use-module (gnu packages guile)
34 #:use-module (gnu packages bdw-gc)
35 #:use-module (gnu packages linux)
36 #:use-module (gnu packages multiprecision)
37 #:use-module (ice-9 match)
38 #:use-module (srfi srfi-1)
39 #:export (%bootstrap-binaries-tarball
40 %binutils-bootstrap-tarball
41 %glibc-bootstrap-tarball
42 %gcc-bootstrap-tarball
43 %guile-bootstrap-tarball
46 %guile-static-stripped))
50 ;;; This module provides tools to build tarballs of the "bootstrap binaries"
51 ;;; used in (gnu packages bootstrap). These statically-linked binaries are
52 ;;; taken for granted and used as the root of the whole bootstrap procedure.
56 (define* (glibc-for-bootstrap #:optional (base glibc))
57 "Return a libc deriving from BASE whose `system' and `popen' functions looks
58 for `sh' in $PATH, and without nscd, and with static NSS modules."
59 (package (inherit base)
60 (source (origin (inherit (package-source base))
61 (patches (cons (search-patch "glibc-bootstrap-system.patch")
62 (origin-patches (package-source base))))))
64 (substitute-keyword-arguments (package-arguments base)
65 ((#:configure-flags flags)
66 ;; Arrange so that getaddrinfo & co. do not contact the nscd,
67 ;; and can use statically-linked NSS modules.
68 `(cons* "--disable-nscd" "--disable-build-nscd"
72 ;; Remove the 'debug' output to allow bit-reproducible builds (when the
73 ;; 'debug' output is used, ELF files end up with a .gnu_debuglink, which
74 ;; includes a CRC of the corresponding debugging symbols; those symbols
75 ;; contain store file names, so the CRC changes at every rebuild.)
76 (outputs (delete "debug" (package-outputs base)))))
78 (define (package-with-relocatable-glibc p)
79 "Return a variant of P that uses the libc as defined by
80 `glibc-for-bootstrap'."
82 (define (cross-bootstrap-libc)
83 (let ((target (%current-target-system)))
85 ;; `cross-libc' already returns a cross libc, so clear
86 ;; %CURRENT-TARGET-SYSTEM.
87 (parameterize ((%current-target-system #f))
88 (cross-libc target)))))
90 ;; Standard inputs with the above libc and corresponding GCC.
93 (if (%current-target-system) ; is this package cross built?
94 `(("cross-libc" ,(cross-bootstrap-libc)))
97 (define (native-inputs)
98 (if (%current-target-system)
99 (let ((target (%current-target-system)))
100 `(("cross-gcc" ,(cross-gcc target
101 (cross-binutils target)
102 (cross-bootstrap-libc)))
103 ("cross-binutils" ,(cross-binutils target))
105 `(("libc" ,(glibc-for-bootstrap))
106 ("gcc" ,(package (inherit gcc-4.8)
107 (outputs '("out")) ; all in one so libgcc_s is easily found
109 `(("libc",(glibc-for-bootstrap))
110 ,@(package-inputs gcc-4.8)))))
111 ,@(fold alist-delete %final-inputs '("libc" "gcc")))))
113 (package-with-explicit-inputs p inputs
114 (current-source-location)
115 #:native-inputs native-inputs))
118 (static-package bash-light))
120 (define %static-inputs
121 ;; Packages that are to be used as %BOOTSTRAP-INPUTS.
122 (let ((coreutils (package (inherit coreutils)
126 "--disable-silent-rules"
127 "--enable-no-install-program=stdbuf,libstdbuf.so"
128 "CFLAGS=-Os -g0" ; smaller, please
129 "LDFLAGS=-static -pthread")
130 #:tests? #f ; signal-related Gnulib tests fail
131 ,@(package-arguments coreutils)))
133 ;; Remove optional dependencies such as GMP. Keep Perl
134 ;; except if it's missing (which is the case when
136 (inputs (match (assoc "perl" (package-inputs coreutils))
140 ;; Remove the 'debug' output (see above for the reason.)
142 (bzip2 (package (inherit bzip2)
144 (substitute-keyword-arguments (package-arguments bzip2)
149 (substitute* "Makefile"
150 (("^LDFLAGS[[:blank:]]*=.*$")
151 "LDFLAGS = -static")))
153 (xz (package (inherit xz)
155 `(#:strip-flags '("--strip-all")
156 #:phases (alist-cons-before
157 'configure 'static-executable
159 ;; Ask Libtool for a static executable.
160 (substitute* "src/xz/Makefile.in"
162 "xz_LDADD = -all-static")))
163 %standard-phases)))))
164 (gawk (package (inherit gawk)
165 (source (origin (inherit (package-source gawk))
166 (patches (cons (search-patch "gawk-shell.patch")
168 (package-source gawk))))))
170 `(;; Starting from gawk 4.1.0, some of the tests for the
171 ;; plug-in mechanism just fail on static builds:
173 ;; ./fts.awk:1: error: can't open shared library `filefuncs' for reading (No such file or directory)
176 ,@(substitute-keyword-arguments (package-arguments gawk)
179 'configure 'no-export-dynamic
181 ;; Since we use `-static', remove
182 ;; `-export-dynamic'.
183 (substitute* "configure"
184 (("-export-dynamic") "")))
186 (inputs (if (%current-target-system)
187 `(("bash" ,%bash-static))
189 (finalize (compose static-package
190 package-with-relocatable-glibc)))
191 `(,@(map (match-lambda
193 (list name (finalize package))))
199 ("coreutils" ,coreutils)
203 ("bash" ,%bash-static))))
205 (define %static-binaries
207 (name "static-binaries")
209 (build-system trivial-build-system)
211 (inputs %static-inputs)
213 `(#:modules ((guix build utils))
216 (use-modules (ice-9 ftw)
223 (define (directory-contents dir)
224 (map (cut string-append dir "/" <>)
225 (scandir dir (negate (cut member <> '("." ".."))))))
227 (define (copy-directory source destination)
228 (for-each (lambda (file)
229 (format #t "copying ~s...~%" file)
231 (string-append destination "/"
233 (directory-contents source)))
235 (let* ((out (assoc-ref %outputs "out"))
236 (bin (string-append out "/bin")))
239 ;; Copy Coreutils binaries.
240 (let* ((coreutils (assoc-ref %build-inputs "coreutils"))
241 (source (string-append coreutils "/bin")))
242 (copy-directory source bin))
244 ;; For the other inputs, copy just one binary, which has the
245 ;; same name as the input.
246 (for-each (match-lambda
248 (let ((source (string-append dir "/bin/" name)))
249 (format #t "copying ~s...~%" source)
251 (string-append bin "/" name)))))
252 (alist-delete "coreutils" %build-inputs))
254 ;; But of course, there are exceptions to this rule.
255 (let ((grep (assoc-ref %build-inputs "grep")))
256 (copy-file (string-append grep "/bin/fgrep")
257 (string-append bin "/fgrep"))
258 (copy-file (string-append grep "/bin/egrep")
259 (string-append bin "/egrep")))
261 ;; Clear references to the store path.
262 (for-each remove-store-references
263 (directory-contents bin))
265 (with-directory-excursion bin
266 ;; Programs such as Perl's build system want these aliases.
267 (symlink "bash" "sh")
268 (symlink "gawk" "awk"))
271 (synopsis "Statically-linked bootstrap binaries")
273 "Binaries used to bootstrap the distribution.")
277 (define %binutils-static
278 ;; Statically-linked Binutils.
279 (package (inherit binutils)
280 (name "binutils-static")
282 `(#:configure-flags (cons "--disable-gold"
283 ,(match (memq #:configure-flags
284 (package-arguments binutils))
285 ((#:configure-flags flags _ ...)
287 #:strip-flags '("--strip-all")
288 #:phases (alist-cons-before
289 'configure 'all-static
291 ;; The `-all-static' libtool flag can only be passed
292 ;; after `configure', since configure tests don't use
293 ;; libtool, and only for executables built with libtool.
294 (substitute* '("binutils/Makefile.in"
297 (("^LDFLAGS =(.*)$" line)
299 "\nAM_LDFLAGS = -static -all-static\n"))))
300 %standard-phases)))))
302 (define %binutils-static-stripped
303 ;; The subset of Binutils that we need.
304 (package (inherit %binutils-static)
305 (name (string-append (package-name %binutils-static) "-stripped"))
306 (build-system trivial-build-system)
309 `(#:modules ((guix build utils))
312 (use-modules (guix build utils))
314 (setvbuf (current-output-port) _IOLBF)
315 (let* ((in (assoc-ref %build-inputs "binutils"))
316 (out (assoc-ref %outputs "out"))
317 (bin (string-append out "/bin")))
319 (for-each (lambda (file)
320 (let ((target (string-append bin "/" file)))
321 (format #t "copying `~a'...~%" file)
322 (copy-file (string-append in "/bin/" file)
324 (remove-store-references target)))
325 '("ar" "as" "ld" "nm" "objcopy" "objdump"
326 "ranlib" "readelf" "size" "strings" "strip"))
328 (inputs `(("binutils" ,%binutils-static)))))
330 (define %glibc-stripped
331 ;; GNU libc's essential shared libraries, dynamic linker, and headers,
332 ;; with all references to store directories stripped. As a result,
333 ;; libc.so is unusable and need to be patched for proper relocation.
334 (let ((glibc (glibc-for-bootstrap)))
335 (package (inherit glibc)
336 (name "glibc-stripped")
337 (build-system trivial-build-system)
339 `(#:modules ((guix build utils))
342 (use-modules (guix build utils))
344 (setvbuf (current-output-port) _IOLBF)
345 (let* ((out (assoc-ref %outputs "out"))
346 (libdir (string-append out "/lib"))
347 (incdir (string-append out "/include"))
348 (libc (assoc-ref %build-inputs "libc"))
349 (linux (assoc-ref %build-inputs "linux-headers")))
351 (for-each (lambda (file)
352 (let ((target (string-append libdir "/"
354 (copy-file file target)
355 (remove-store-references target)))
356 (find-files (string-append libc "/lib")
357 "^(crt.*|ld.*|lib(c|m|dl|rt|pthread|nsl|util).*\\.so(\\..*)?|libc_nonshared\\.a)$"))
359 (copy-recursively (string-append libc "/include") incdir)
361 ;; Copy some of the Linux-Libre headers that glibc headers
363 (mkdir (string-append incdir "/linux"))
364 (for-each (lambda (file)
365 (copy-file (string-append linux "/include/linux/" file)
366 (string-append incdir "/linux/"
368 '("limits.h" "errno.h" "socket.h" "kernel.h"
369 "sysctl.h" "param.h" "ioctl.h" "types.h"
370 "posix_types.h" "stddef.h"))
372 (copy-recursively (string-append linux "/include/asm")
373 (string-append incdir "/asm"))
374 (copy-recursively (string-append linux "/include/asm-generic")
375 (string-append incdir "/asm-generic"))
377 ;; Remove the '.install' and '..install.cmd' files; the latter
378 ;; contains store paths, which prevents bit reproducibility.
379 (for-each delete-file (find-files incdir "\\.install"))
382 (inputs `(("libc" ,(let ((target (%current-target-system)))
385 (parameterize ((%current-target-system #f))
386 (cross-libc target)))
388 ("linux-headers" ,linux-libre-headers)))
391 (outputs '("out")))))
394 ;; A statically-linked GCC, with stripped-down functionality.
395 (package-with-relocatable-glibc
396 (package (inherit gcc-4.8)
398 (outputs '("out")) ; all in one
400 `(#:modules ((guix build utils)
401 (guix build gnu-build-system)
405 ,@(substitute-keyword-arguments (package-arguments gcc-4.8)
407 ((#:implicit-inputs? _) #t)
408 ((#:configure-flags flags)
410 ;; We don't need a full bootstrap here.
411 "--disable-bootstrap"
413 ;; Make sure '-static' is passed where it matters.
414 "--with-stage1-ldflags=-static"
416 ;; GCC 4.8+ requires a C++ compiler and library.
417 "--enable-languages=c,c++"
419 ;; Make sure gcc-nm doesn't require liblto_plugin.so.
424 "--disable-libmudflap"
425 "--disable-libatomic"
426 "--disable-libsanitizer"
430 "--disable-libquadmath"
431 "--disable-decimal-float")
432 (remove (cut string-match "--(.*plugin|enable-languages)" <>)
435 (if (%current-target-system)
436 `(;; When doing a Canadian cross, we need GMP/MPFR/MPC both
437 ;; as target inputs and as native inputs; the latter is
438 ;; needed when building build-time tools ('genconstants',
439 ;; etc.) Failing to do that leads to misdetections of
440 ;; declarations by 'gcc/configure', and eventually to
441 ;; duplicate declarations as reported in
442 ;; <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59217>.
444 ("mpfr-native" ,mpfr)
446 ,@(package-native-inputs gcc-4.8))
447 (package-native-inputs gcc-4.8))))))
449 (define %gcc-stripped
450 ;; The subset of GCC files needed for bootstrap.
451 (package (inherit gcc-4.8)
452 (name "gcc-stripped")
453 (build-system trivial-build-system)
455 (outputs '("out")) ;only one output
457 `(#:modules ((guix build utils))
460 (use-modules (srfi srfi-1)
464 (setvbuf (current-output-port) _IOLBF)
465 (let* ((out (assoc-ref %outputs "out"))
466 (bindir (string-append out "/bin"))
467 (libdir (string-append out "/lib"))
468 (includedir (string-append out "/include"))
469 (libexecdir (string-append out "/libexec"))
470 (gcc (assoc-ref %build-inputs "gcc")))
471 (copy-recursively (string-append gcc "/bin") bindir)
472 (for-each remove-store-references
473 (find-files bindir ".*"))
475 (copy-recursively (string-append gcc "/lib") libdir)
476 (for-each remove-store-references
477 (remove (cut string-suffix? ".h" <>)
478 (find-files libdir ".*")))
480 (copy-recursively (string-append gcc "/libexec")
482 (for-each remove-store-references
483 (find-files libexecdir ".*"))
485 ;; Starting from GCC 4.8, helper programs built natively
486 ;; (‘genchecksum’, ‘gcc-nm’, etc.) rely on C++ headers.
487 (copy-recursively (string-append gcc "/include/c++")
488 (string-append includedir "/c++"))
490 ;; For native builds, check whether the binaries actually work.
491 ,(if (%current-target-system)
493 '(every (lambda (prog)
494 (zero? (system* (string-append gcc "/bin/" prog)
496 '("gcc" "g++" "cpp")))))))
497 (inputs `(("gcc" ,%gcc-static)))))
499 (define %guile-static
500 ;; A statically-linked Guile that is relocatable--i.e., it can search
501 ;; .scm and .go files relative to its installation directory, rather
502 ;; than in hard-coded configure-time paths.
503 (let* ((patches (cons* (search-patch "guile-relocatable.patch")
504 (search-patch "guile-default-utf8.patch")
505 (search-patch "guile-linux-syscalls.patch")
506 (origin-patches (package-source guile-2.0))))
507 (source (origin (inherit (package-source guile-2.0))
509 (guile (package (inherit guile-2.0)
510 (name (string-append (package-name guile-2.0) "-static"))
512 (synopsis "Statically-linked and relocatable Guile")
514 ;; Remove the 'debug' output (see above for the reason.)
515 (outputs (delete "debug" (package-outputs guile-2.0)))
519 ,@(alist-delete "bdw-gc"
520 (package-propagated-inputs guile-2.0))))
522 `(;; When `configure' checks for ltdl availability, it
523 ;; doesn't try to link using libtool, and thus fails
524 ;; because of a missing -ldl. Work around that.
525 #:configure-flags '("LDFLAGS=-ldl")
527 #:phases (alist-cons-before
528 'configure 'static-guile
530 (substitute* "libguile/Makefile.in"
531 ;; Create a statically-linked `guile'
533 (("^guile_LDFLAGS =")
534 "guile_LDFLAGS = -all-static")
536 ;; Add `-ldl' *after* libguile-2.0.la.
537 (("^guile_LDADD =(.*)$" _ ldadd)
538 (string-append "guile_LDADD = "
539 (string-trim-right ldadd)
543 ;; There are uses of `dynamic-link' in
544 ;; {foreign,coverage}.test that don't fly here.
546 (package-with-relocatable-glibc (static-package guile))))
548 (define %guile-static-stripped
549 ;; A stripped static Guile binary, for use during bootstrap.
550 (package (inherit %guile-static)
551 (name "guile-static-stripped")
552 (build-system trivial-build-system)
554 `(#:modules ((guix build utils))
557 (use-modules (guix build utils))
559 (let* ((in (assoc-ref %build-inputs "guile"))
560 (out (assoc-ref %outputs "out"))
561 (guile1 (string-append in "/bin/guile"))
562 (guile2 (string-append out "/bin/guile")))
563 (mkdir-p (string-append out "/share/guile/2.0"))
564 (copy-recursively (string-append in "/share/guile/2.0")
565 (string-append out "/share/guile/2.0"))
567 (mkdir-p (string-append out "/lib/guile/2.0/ccache"))
568 (copy-recursively (string-append in "/lib/guile/2.0/ccache")
569 (string-append out "/lib/guile/2.0/ccache"))
571 (mkdir (string-append out "/bin"))
572 (copy-file guile1 guile2)
574 ;; Does the relocated Guile work?
575 (and ,(if (%current-target-system)
577 '(zero? (system* guile2 "--version")))
579 ;; Strip store references.
580 (remove-store-references guile2)
582 ;; Does the stripped Guile work? If it aborts, it could be
583 ;; that it tries to open iconv descriptors and fails because
584 ;; libc's iconv data isn't available (see
585 ;; `guile-default-utf8.patch'.)
586 ,(if (%current-target-system)
588 '(zero? (system* guile2 "--version")))))))))
589 (inputs `(("guile" ,%guile-static)))
591 (synopsis "Minimal statically-linked and relocatable Guile")))
593 (define (tarball-package pkg)
594 "Return a package containing a tarball of PKG."
595 (package (inherit pkg)
596 (location (source-properties->location (current-source-location)))
597 (name (string-append (package-name pkg) "-tarball"))
598 (build-system trivial-build-system)
599 (native-inputs `(("tar" ,tar)
601 (inputs `(("input" ,pkg)))
603 (let ((name (package-name pkg))
604 (version (package-version pkg)))
605 `(#:modules ((guix build utils))
608 (use-modules (guix build utils))
609 (let ((out (assoc-ref %outputs "out"))
610 (input (assoc-ref %build-inputs "input"))
611 (tar (assoc-ref %build-inputs "tar"))
612 (xz (assoc-ref %build-inputs "xz")))
614 (set-path-environment-variable "PATH" '("bin") (list tar xz))
615 (with-directory-excursion input
616 (zero? (system* "tar" "cJvf"
617 (string-append out "/"
620 ,(or (%current-target-system)
625 (define %bootstrap-binaries-tarball
626 ;; A tarball with the statically-linked bootstrap binaries.
627 (tarball-package %static-binaries))
629 (define %binutils-bootstrap-tarball
630 ;; A tarball with the statically-linked Binutils programs.
631 (tarball-package %binutils-static-stripped))
633 (define %glibc-bootstrap-tarball
634 ;; A tarball with GNU libc's shared libraries, dynamic linker, and headers.
635 (tarball-package %glibc-stripped))
637 (define %gcc-bootstrap-tarball
638 ;; A tarball with a dynamic-linked GCC and its headers.
639 (tarball-package %gcc-stripped))
641 (define %guile-bootstrap-tarball
642 ;; A tarball with the statically-linked, relocatable Guile.
643 (tarball-package %guile-static-stripped))
645 (define %bootstrap-tarballs
646 ;; A single derivation containing all the bootstrap tarballs, for
649 (name "bootstrap-tarballs")
652 (build-system trivial-build-system)
654 `(#:modules ((guix build utils))
656 (let ((out (assoc-ref %outputs "out")))
657 (use-modules (guix build utils)
661 (setvbuf (current-output-port) _IOLBF)
664 (for-each (match-lambda
666 (for-each (lambda (file)
667 (format #t "~a -> ~a~%" file out)
668 (symlink file (basename file)))
669 (find-files directory "\\.tar\\."))))
672 (inputs `(("guile-tarball" ,%guile-bootstrap-tarball)
673 ("gcc-tarball" ,%gcc-bootstrap-tarball)
674 ("binutils-tarball" ,%binutils-bootstrap-tarball)
675 ("glibc-tarball" ,%glibc-bootstrap-tarball)
676 ("coreutils&co-tarball" ,%bootstrap-binaries-tarball)))
682 ;;; make-bootstrap.scm ends here