1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2012, 2013 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 base)
27 #:use-module (gnu packages bash)
28 #:use-module (gnu packages compression)
29 #:use-module (gnu packages gawk)
30 #:use-module (gnu packages guile)
31 #:use-module (gnu packages linux)
32 #:use-module (gnu packages multiprecision)
33 #:use-module (ice-9 match)
34 #:use-module (srfi srfi-1)
35 #:export (%bootstrap-binaries-tarball
36 %binutils-bootstrap-tarball
37 %glibc-bootstrap-tarball
38 %gcc-bootstrap-tarball
39 %guile-bootstrap-tarball
44 ;;; This modules provides tools to build tarballs of the "bootstrap binaries"
45 ;;; used in (gnu packages bootstrap). These statically-linked binaries are
46 ;;; taken for granted and used as the root of the whole bootstrap procedure.
50 (define %glibc-for-bootstrap
51 ;; A libc whose `system' and `popen' functions looks for `sh' in $PATH,
52 ;; without nscd, and with static NSS modules.
53 (package (inherit glibc-final)
55 (substitute-keyword-arguments (package-arguments glibc-final)
57 `(cons (assoc-ref %build-inputs "patch/system") ,patches))
58 ((#:configure-flags flags)
59 ;; Arrange so that getaddrinfo & co. do not contact the nscd,
60 ;; and can use statically-linked NSS modules.
61 `(cons* "--disable-nscd" "--disable-build-nscd"
65 `(("patch/system" ,(search-patch "glibc-bootstrap-system.patch"))
66 ,@(package-inputs glibc-final)))))
68 (define %standard-inputs-with-relocatable-glibc
69 ;; Standard inputs with the above libc and corresponding GCC.
70 `(("libc", %glibc-for-bootstrap)
71 ("gcc" ,(package-with-explicit-inputs
73 `(("libc",%glibc-for-bootstrap)
74 ,@(alist-delete "libc" %final-inputs))
75 (current-source-location)))
76 ,@(fold alist-delete %final-inputs '("libc" "gcc"))))
79 (static-package bash-light))
81 (define %static-inputs
82 ;; Packages that are to be used as %BOOTSTRAP-INPUTS.
83 (let ((coreutils (package (inherit coreutils)
87 "--disable-silent-rules"
88 "--enable-no-install-program=stdbuf,libstdbuf.so"
89 "CFLAGS=-Os -g0" ; smaller, please
90 "LDFLAGS=-static -pthread")
91 #:tests? #f ; signal-related Gnulib tests fail
92 ,@(package-arguments coreutils)))
94 ;; Remove optional dependencies such as GMP.
95 (inputs `(,(assoc "perl" (package-inputs coreutils))))))
96 (bzip2 (package (inherit bzip2)
98 (substitute-keyword-arguments (package-arguments bzip2)
103 (substitute* "Makefile"
104 (("^LDFLAGS[[:blank:]]*=.*$")
105 "LDFLAGS = -static")))
107 (xz (package (inherit xz)
109 `(#:strip-flags '("--strip-all")
110 #:phases (alist-cons-before
111 'configure 'static-executable
113 ;; Ask Libtool for a static executable.
114 (substitute* "src/xz/Makefile.in"
116 "xz_LDADD = -all-static")))
117 %standard-phases)))))
118 (gawk (package (inherit gawk)
120 `(#:patches (list (assoc-ref %build-inputs "patch/sh"))
121 ,@(substitute-keyword-arguments (package-arguments gawk)
124 'configure 'no-export-dynamic
126 ;; Since we use `-static', remove
127 ;; `-export-dynamic'.
128 (substitute* "configure"
129 (("-export-dynamic") "")))
131 (inputs `(("patch/sh" ,(search-patch "gawk-shell.patch"))))))
132 (finalize (lambda (p)
133 (static-package (package-with-explicit-inputs
135 %standard-inputs-with-relocatable-glibc)
136 (current-source-location)))))
137 `(,@(map (match-lambda
139 (list name (finalize package))))
145 ("coreutils" ,coreutils)
149 ("bash" ,%bash-static)
150 ;; ("ld-wrapper" ,ld-wrapper)
151 ;; ("binutils" ,binutils-final)
152 ;; ("gcc" ,gcc-final)
153 ;; ("libc" ,glibc-final)
156 (define %static-binaries
158 (name "static-binaries")
160 (build-system trivial-build-system)
162 (inputs %static-inputs)
164 `(#:modules ((guix build utils))
167 (use-modules (ice-9 ftw)
174 (define (directory-contents dir)
175 (map (cut string-append dir "/" <>)
176 (scandir dir (negate (cut member <> '("." ".."))))))
178 (define (copy-directory source destination)
179 (for-each (lambda (file)
180 (format #t "copying ~s...~%" file)
182 (string-append destination "/"
184 (directory-contents source)))
186 (let* ((out (assoc-ref %outputs "out"))
187 (bin (string-append out "/bin")))
190 ;; Copy Coreutils binaries.
191 (let* ((coreutils (assoc-ref %build-inputs "coreutils"))
192 (source (string-append coreutils "/bin")))
193 (copy-directory source bin))
195 ;; For the other inputs, copy just one binary, which has the
196 ;; same name as the input.
197 (for-each (match-lambda
199 (let ((source (string-append dir "/bin/" name)))
200 (format #t "copying ~s...~%" source)
202 (string-append bin "/" name)))))
203 (alist-delete "coreutils" %build-inputs))
205 ;; But of course, there are exceptions to this rule.
206 (let ((grep (assoc-ref %build-inputs "grep")))
207 (copy-file (string-append grep "/bin/fgrep")
208 (string-append bin "/fgrep"))
209 (copy-file (string-append grep "/bin/egrep")
210 (string-append bin "/egrep")))
212 ;; Clear references to the store path.
213 (for-each remove-store-references
214 (directory-contents bin))
216 (with-directory-excursion bin
217 ;; Programs such as Perl's build system want these aliases.
218 (symlink "bash" "sh")
219 (symlink "gawk" "awk"))
222 (synopsis "Statically-linked bootstrap binaries")
224 "Binaries used to bootstrap the distribution.")
228 (define %binutils-static
229 ;; Statically-linked Binutils.
230 (package (inherit binutils)
231 (name "binutils-static")
233 `(#:configure-flags '("--disable-gold" "--with-lib-path=/no-ld-lib-path")
234 #:strip-flags '("--strip-all")
235 #:phases (alist-cons-before
236 'configure 'all-static
238 ;; The `-all-static' libtool flag can only be passed
239 ;; after `configure', since configure tests don't use
240 ;; libtool, and only for executables built with libtool.
241 (substitute* '("binutils/Makefile.in"
244 (("^LDFLAGS =(.*)$" line)
246 "\nAM_LDFLAGS = -static -all-static\n"))))
247 %standard-phases)))))
249 (define %binutils-static-stripped
250 ;; The subset of Binutils that we need.
251 (package (inherit %binutils-static)
252 (build-system trivial-build-system)
254 `(#:modules ((guix build utils))
257 (use-modules (guix build utils))
259 (setvbuf (current-output-port) _IOLBF)
260 (let* ((in (assoc-ref %build-inputs "binutils"))
261 (out (assoc-ref %outputs "out"))
262 (bin (string-append out "/bin")))
264 (for-each (lambda (file)
265 (let ((target (string-append bin "/" file)))
266 (format #t "copying `~a'...~%" file)
267 (copy-file (string-append in "/bin/" file)
269 (remove-store-references target)))
270 '("ar" "as" "ld" "nm" "objcopy" "objdump"
271 "ranlib" "readelf" "size" "strings" "strip"))
273 (inputs `(("binutils" ,%binutils-static)))))
275 (define %glibc-stripped
276 ;; GNU libc's essential shared libraries, dynamic linker, and headers,
277 ;; with all references to store directories stripped. As a result,
278 ;; libc.so is unusable and need to be patched for proper relocation.
279 (let ((glibc %glibc-for-bootstrap))
280 (package (inherit glibc)
281 (name "glibc-stripped")
282 (build-system trivial-build-system)
284 `(#:modules ((guix build utils))
287 (use-modules (guix build utils))
289 (setvbuf (current-output-port) _IOLBF)
290 (let* ((out (assoc-ref %outputs "out"))
291 (libdir (string-append out "/lib"))
292 (incdir (string-append out "/include"))
293 (libc (assoc-ref %build-inputs "libc"))
294 (linux (assoc-ref %build-inputs "linux-headers")))
296 (for-each (lambda (file)
297 (let ((target (string-append libdir "/"
299 (copy-file file target)
300 (remove-store-references target)))
301 (find-files (string-append libc "/lib")
302 "^(crt.*|ld.*|lib(c|m|dl|rt|pthread|nsl|util).*\\.so(\\..*)?|libc_nonshared\\.a)$"))
304 (copy-recursively (string-append libc "/include") incdir)
306 ;; Copy some of the Linux-Libre headers that glibc headers
308 (mkdir (string-append incdir "/linux"))
309 (for-each (lambda (file)
310 (copy-file (string-append linux "/include/linux/" file)
311 (string-append incdir "/linux/"
313 '("limits.h" "errno.h" "socket.h" "kernel.h"
314 "sysctl.h" "param.h" "ioctl.h" "types.h"
315 "posix_types.h" "stddef.h"))
317 (copy-recursively (string-append linux "/include/asm")
318 (string-append incdir "/asm"))
319 (copy-recursively (string-append linux "/include/asm-generic")
320 (string-append incdir "/asm-generic"))
322 (inputs `(("libc" ,glibc)
323 ("linux-headers" ,linux-libre-headers))))))
326 ;; A statically-linked GCC, with stripped-down functionality.
327 (package-with-explicit-inputs
328 (package (inherit gcc-final)
331 `(#:modules ((guix build utils)
332 (guix build gnu-build-system)
336 ,@(substitute-keyword-arguments (package-arguments gcc-final)
338 ((#:implicit-inputs? _) #t)
339 ((#:configure-flags flags)
343 "--enable-languages=c"
344 "--disable-libmudflap"
347 "--disable-libquadmath"
348 "--disable-decimal-float")
349 (remove (cut string-match "--(.*plugin|enable-languages)" <>)
351 ((#:make-flags flags)
352 `(cons "BOOT_LDFLAGS=-static" ,flags)))))
353 (inputs `(("gmp-source" ,(package-source gmp))
354 ("mpfr-source" ,(package-source mpfr))
355 ("mpc-source" ,(package-source mpc))
356 ("binutils" ,binutils-final)
357 ,@(package-inputs gcc-4.7))))
358 %standard-inputs-with-relocatable-glibc))
360 (define %gcc-stripped
361 ;; The subset of GCC files needed for bootstrap.
362 (package (inherit gcc-4.7)
363 (name "gcc-stripped")
364 (build-system trivial-build-system)
367 `(#:modules ((guix build utils))
370 (use-modules (srfi srfi-1)
374 (setvbuf (current-output-port) _IOLBF)
375 (let* ((out (assoc-ref %outputs "out"))
376 (bindir (string-append out "/bin"))
377 (libdir (string-append out "/lib"))
378 (libexecdir (string-append out "/libexec"))
379 (gcc (assoc-ref %build-inputs "gcc")))
380 (copy-recursively (string-append gcc "/bin") bindir)
381 (for-each remove-store-references
382 (find-files bindir ".*"))
384 (copy-recursively (string-append gcc "/lib") libdir)
385 (for-each remove-store-references
386 (remove (cut string-suffix? ".h" <>)
387 (find-files libdir ".*")))
389 (copy-recursively (string-append gcc "/libexec")
391 (for-each remove-store-references
392 (find-files libexecdir ".*"))
394 (inputs `(("gcc" ,%gcc-static)))))
396 (define %guile-static
397 ;; A statically-linked Guile that is relocatable--i.e., it can search
398 ;; .scm and .go files relative to its installation directory, rather
399 ;; than in hard-coded configure-time paths.
400 (let ((guile (package (inherit guile-2.0)
402 `(("patch/relocatable"
403 ,(search-patch "guile-relocatable.patch"))
405 ,(search-patch "guile-default-utf8.patch"))
406 ,@(package-inputs guile-2.0)))
408 `(;; When `configure' checks for ltdl availability, it
409 ;; doesn't try to link using libtool, and thus fails
410 ;; because of a missing -ldl. Work around that.
411 #:configure-flags '("LDFLAGS=-ldl")
413 #:phases (alist-cons-before
414 'configure 'static-guile
416 (substitute* "libguile/Makefile.in"
417 ;; Create a statically-linked `guile'
419 (("^guile_LDFLAGS =")
420 "guile_LDFLAGS = -all-static")
422 ;; Add `-ldl' *after* libguile-2.0.la.
423 (("^guile_LDADD =(.*)$" _ ldadd)
424 (string-append "guile_LDADD = "
425 (string-trim-right ldadd)
429 ;; Allow Guile to be relocated, as is needed during
432 (list (assoc-ref %build-inputs "patch/relocatable")
433 (assoc-ref %build-inputs "patch/utf8"))
435 ;; There are uses of `dynamic-link' in
436 ;; {foreign,coverage}.test that don't fly here.
438 (package-with-explicit-inputs (static-package guile)
439 %standard-inputs-with-relocatable-glibc
440 (current-source-location))))
442 (define %guile-static-stripped
443 ;; A stripped static Guile binary, for use during bootstrap.
444 (package (inherit %guile-static)
445 (name "guile-static-stripped")
446 (build-system trivial-build-system)
448 `(#:modules ((guix build utils))
451 (use-modules (guix build utils))
453 (let ((in (assoc-ref %build-inputs "guile"))
454 (out (assoc-ref %outputs "out")))
455 (mkdir-p (string-append out "/share/guile/2.0"))
456 (copy-recursively (string-append in "/share/guile/2.0")
457 (string-append out "/share/guile/2.0"))
459 (mkdir-p (string-append out "/lib/guile/2.0/ccache"))
460 (copy-recursively (string-append in "/lib/guile/2.0/ccache")
461 (string-append out "/lib/guile/2.0/ccache"))
463 (mkdir (string-append out "/bin"))
464 (copy-file (string-append in "/bin/guile")
465 (string-append out "/bin/guile"))
466 (remove-store-references (string-append out "/bin/guile"))
468 (inputs `(("guile" ,%guile-static)))))
470 (define (tarball-package pkg)
471 "Return a package containing a tarball of PKG."
472 (package (inherit pkg)
473 (location (source-properties->location (current-source-location)))
474 (name (string-append (package-name pkg) "-tarball"))
475 (build-system trivial-build-system)
476 (inputs `(("tar" ,tar)
480 (let ((name (package-name pkg))
481 (version (package-version pkg)))
482 `(#:modules ((guix build utils))
485 (use-modules (guix build utils))
486 (let ((out (assoc-ref %outputs "out"))
487 (input (assoc-ref %build-inputs "input"))
488 (tar (assoc-ref %build-inputs "tar"))
489 (xz (assoc-ref %build-inputs "xz")))
491 (set-path-environment-variable "PATH" '("bin") (list tar xz))
492 (with-directory-excursion input
493 (zero? (system* "tar" "cJvf"
494 (string-append out "/"
496 "-" ,(%current-system)
500 (define %bootstrap-binaries-tarball
501 ;; A tarball with the statically-linked bootstrap binaries.
502 (tarball-package %static-binaries))
504 (define %binutils-bootstrap-tarball
505 ;; A tarball with the statically-linked Binutils programs.
506 (tarball-package %binutils-static-stripped))
508 (define %glibc-bootstrap-tarball
509 ;; A tarball with GNU libc's shared libraries, dynamic linker, and headers.
510 (tarball-package %glibc-stripped))
512 (define %gcc-bootstrap-tarball
513 ;; A tarball with a dynamic-linked GCC and its headers.
514 (tarball-package %gcc-stripped))
516 (define %guile-bootstrap-tarball
517 ;; A tarball with the statically-linked, relocatable Guile.
518 (tarball-package %guile-static-stripped))
520 (define %bootstrap-tarballs
521 ;; A single derivation containing all the bootstrap tarballs, for
524 (name "bootstrap-tarballs")
527 (build-system trivial-build-system)
529 `(#:modules ((guix build utils))
531 (let ((out (assoc-ref %outputs "out")))
532 (use-modules (guix build utils)
536 (setvbuf (current-output-port) _IOLBF)
539 (for-each (match-lambda
541 (for-each (lambda (file)
542 (format #t "~a -> ~a~%" file out)
543 (symlink file (basename file)))
544 (find-files directory "\\.tar\\."))))
547 (inputs `(("guile-tarball" ,%guile-bootstrap-tarball)
548 ("gcc-tarball" ,%gcc-bootstrap-tarball)
549 ("binutils-tarball" ,%binutils-bootstrap-tarball)
550 ("glibc-tarball" ,%glibc-bootstrap-tarball)
551 ("coreutils&co-tarball" ,%bootstrap-binaries-tarball)))
557 ;;; make-bootstrap.scm ends here