;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
#:use-module (guix build-system trivial)
#:use-module (guix build-system gnu)
#:use-module ((gnu packages) #:select (search-patch))
+ #:use-module ((gnu packages commencement) #:select (%final-inputs))
#:use-module (gnu packages base)
+ #:use-module (gnu packages cross-base)
#:use-module (gnu packages bash)
#:use-module (gnu packages compression)
#:use-module (gnu packages gawk)
%glibc-bootstrap-tarball
%gcc-bootstrap-tarball
%guile-bootstrap-tarball
- %bootstrap-tarballs))
+ %bootstrap-tarballs
+
+ %guile-static-stripped))
;;; Commentary:
;;;
-;;; This modules provides tools to build tarballs of the "bootstrap binaries"
+;;; This module provides tools to build tarballs of the "bootstrap binaries"
;;; used in (gnu packages bootstrap). These statically-linked binaries are
;;; taken for granted and used as the root of the whole bootstrap procedure.
;;;
;;; Code:
-(define %glibc-for-bootstrap
- ;; A libc whose `system' and `popen' functions looks for `sh' in $PATH,
- ;; without nscd, and with static NSS modules.
- (package (inherit glibc-final)
+(define* (glibc-for-bootstrap #:optional (base glibc))
+ "Return a libc deriving from BASE whose `system' and `popen' functions looks
+for `sh' in $PATH, and without nscd, and with static NSS modules."
+ (package (inherit base)
+ (source (origin (inherit (package-source base))
+ (patches (cons (search-patch "glibc-bootstrap-system.patch")
+ (origin-patches (package-source base))))))
(arguments
- (substitute-keyword-arguments (package-arguments glibc-final)
- ((#:patches patches)
- `(cons (assoc-ref %build-inputs "patch/system") ,patches))
+ (substitute-keyword-arguments (package-arguments base)
((#:configure-flags flags)
;; Arrange so that getaddrinfo & co. do not contact the nscd,
;; and can use statically-linked NSS modules.
`(cons* "--disable-nscd" "--disable-build-nscd"
"--enable-static-nss"
,flags))))
- (inputs
- `(("patch/system" ,(search-patch "glibc-bootstrap-system.patch"))
- ,@(package-inputs glibc-final)))))
-(define %standard-inputs-with-relocatable-glibc
+ ;; Remove the 'debug' output to allow bit-reproducible builds (when the
+ ;; 'debug' output is used, ELF files end up with a .gnu_debuglink, which
+ ;; includes a CRC of the corresponding debugging symbols; those symbols
+ ;; contain store file names, so the CRC changes at every rebuild.)
+ (outputs (delete "debug" (package-outputs base)))))
+
+(define (package-with-relocatable-glibc p)
+ "Return a variant of P that uses the libc as defined by
+`glibc-for-bootstrap'."
+
+ (define (cross-bootstrap-libc)
+ (let ((target (%current-target-system)))
+ (glibc-for-bootstrap
+ ;; `cross-libc' already returns a cross libc, so clear
+ ;; %CURRENT-TARGET-SYSTEM.
+ (parameterize ((%current-target-system #f))
+ (cross-libc target)))))
+
;; Standard inputs with the above libc and corresponding GCC.
- `(("libc", %glibc-for-bootstrap)
- ("gcc" ,(package-with-explicit-inputs
- gcc-4.7
- `(("libc",%glibc-for-bootstrap)
- ,@(alist-delete "libc" %final-inputs))
- (current-source-location)))
- ,@(fold alist-delete %final-inputs '("libc" "gcc"))))
+
+ (define (inputs)
+ (if (%current-target-system) ; is this package cross built?
+ `(("cross-libc" ,(cross-bootstrap-libc)))
+ '()))
+
+ (define (native-inputs)
+ (if (%current-target-system)
+ (let ((target (%current-target-system)))
+ `(("cross-gcc" ,(cross-gcc target
+ (cross-binutils target)
+ (cross-bootstrap-libc)))
+ ("cross-binutils" ,(cross-binutils target))
+ ,@%final-inputs))
+ `(("libc" ,(glibc-for-bootstrap))
+ ("gcc" ,(package (inherit gcc-4.8)
+ (outputs '("out")) ; all in one so libgcc_s is easily found
+ (inputs
+ `(("libc",(glibc-for-bootstrap))
+ ,@(package-inputs gcc-4.8)))))
+ ,@(fold alist-delete %final-inputs '("libc" "gcc")))))
+
+ (package-with-explicit-inputs p inputs
+ (current-source-location)
+ #:native-inputs native-inputs))
(define %bash-static
(static-package bash-light))
;; cross-compiling).
(inputs (match (assoc "perl" (package-inputs coreutils))
(#f '())
- (x (list x))))))
+ (x (list x))))
+
+ ;; Remove the 'debug' output (see above for the reason.)
+ (outputs '("out"))))
(bzip2 (package (inherit bzip2)
(arguments
(substitute-keyword-arguments (package-arguments bzip2)
"xz_LDADD = -all-static")))
%standard-phases)))))
(gawk (package (inherit gawk)
+ (source (origin (inherit (package-source gawk))
+ (patches (cons (search-patch "gawk-shell.patch")
+ (origin-patches
+ (package-source gawk))))))
(arguments
- `(#:patches (list (assoc-ref %build-inputs "patch/sh"))
+ `(;; Starting from gawk 4.1.0, some of the tests for the
+ ;; plug-in mechanism just fail on static builds:
+ ;;
+ ;; ./fts.awk:1: error: can't open shared library `filefuncs' for reading (No such file or directory)
+ #:tests? #f
+
,@(substitute-keyword-arguments (package-arguments gawk)
((#:phases phases)
`(alist-cons-before
(substitute* "configure"
(("-export-dynamic") "")))
,phases)))))
- (inputs `(("patch/sh" ,(search-patch "gawk-shell.patch"))))))
- (finalize (lambda (p)
- (static-package (package-with-explicit-inputs
- p
- %standard-inputs-with-relocatable-glibc)
- (current-source-location)))))
+ (inputs (if (%current-target-system)
+ `(("bash" ,%bash-static))
+ '()))))
+ (finalize (compose static-package
+ package-with-relocatable-glibc)))
`(,@(map (match-lambda
((name package)
(list name (finalize package))))
("sed" ,sed)
("grep" ,grep)
("gawk" ,gawk)))
- ("bash" ,%bash-static)
- ;; ("ld-wrapper" ,ld-wrapper)
- ;; ("binutils" ,binutils-final)
- ;; ("gcc" ,gcc-final)
- ;; ("libc" ,glibc-final)
- )))
+ ("bash" ,%bash-static))))
(define %static-binaries
(package
(package (inherit binutils)
(name "binutils-static")
(arguments
- `(#:configure-flags '("--disable-gold" "--with-lib-path=/no-ld-lib-path")
+ `(#:configure-flags (cons "--disable-gold"
+ ,(match (memq #:configure-flags
+ (package-arguments binutils))
+ ((#:configure-flags flags _ ...)
+ flags)))
#:strip-flags '("--strip-all")
#:phases (alist-cons-before
'configure 'all-static
;; GNU libc's essential shared libraries, dynamic linker, and headers,
;; with all references to store directories stripped. As a result,
;; libc.so is unusable and need to be patched for proper relocation.
- (let ((glibc %glibc-for-bootstrap))
+ (let ((glibc (glibc-for-bootstrap)))
(package (inherit glibc)
(name "glibc-stripped")
(build-system trivial-build-system)
(string-append incdir "/asm"))
(copy-recursively (string-append linux "/include/asm-generic")
(string-append incdir "/asm-generic"))
+
#t))))
- (inputs `(("libc" ,glibc)
+ (inputs `(("libc" ,(let ((target (%current-target-system)))
+ (if target
+ (glibc-for-bootstrap
+ (parameterize ((%current-target-system #f))
+ (cross-libc target)))
+ glibc)))
("linux-headers" ,linux-libre-headers)))
;; Only one output.
(define %gcc-static
;; A statically-linked GCC, with stripped-down functionality.
- (package-with-explicit-inputs
- (package (inherit gcc-final)
+ (package-with-relocatable-glibc
+ (package (inherit gcc-4.8)
(name "gcc-static")
+ (outputs '("out")) ; all in one
(arguments
`(#:modules ((guix build utils)
(guix build gnu-build-system)
(srfi srfi-1)
(srfi srfi-26)
(ice-9 regex))
- ,@(substitute-keyword-arguments (package-arguments gcc-final)
+ ,@(substitute-keyword-arguments (package-arguments gcc-4.8)
((#:guile _) #f)
((#:implicit-inputs? _) #t)
((#:configure-flags flags)
`(append (list
+ ;; We don't need a full bootstrap here.
+ "--disable-bootstrap"
+
+ ;; Make sure '-static' is passed where it matters.
+ "--with-stage1-ldflags=-static"
+
+ ;; GCC 4.8+ requires a C++ compiler and library.
+ "--enable-languages=c,c++"
+
+ ;; Make sure gcc-nm doesn't require liblto_plugin.so.
+ "--disable-lto"
+
"--disable-shared"
"--disable-plugin"
- "--enable-languages=c"
"--disable-libmudflap"
+ "--disable-libatomic"
+ "--disable-libsanitizer"
+ "--disable-libitm"
"--disable-libgomp"
"--disable-libssp"
"--disable-libquadmath"
"--disable-decimal-float")
(remove (cut string-match "--(.*plugin|enable-languages)" <>)
,flags)))
- ((#:make-flags flags)
- `(cons "BOOT_LDFLAGS=-static" ,flags)))))
- (inputs `(("gmp-source" ,(package-source gmp))
- ("mpfr-source" ,(package-source mpfr))
- ("mpc-source" ,(package-source mpc))
- ("binutils" ,binutils-final)
- ,@(package-inputs gcc-4.7))))
- %standard-inputs-with-relocatable-glibc))
+ ((#:phases phases)
+ `(alist-cons-after
+ 'pre-configure 'remove-lgcc_s
+ (lambda _
+ ;; Remove the '-lgcc_s' added to GNU_USER_TARGET_LIB_SPEC in
+ ;; the 'pre-configure phase of our main gcc package, because
+ ;; that shared library is not present in this static gcc. See
+ ;; <https://lists.gnu.org/archive/html/guix-devel/2015-01/msg00008.html>.
+ (substitute* (find-files "gcc/config"
+ "^gnu-user.*\\.h$")
+ ((" -lgcc_s}}") "}}")))
+ ,phases)))))
+ (native-inputs
+ (if (%current-target-system)
+ `(;; When doing a Canadian cross, we need GMP/MPFR/MPC both
+ ;; as target inputs and as native inputs; the latter is
+ ;; needed when building build-time tools ('genconstants',
+ ;; etc.) Failing to do that leads to misdetections of
+ ;; declarations by 'gcc/configure', and eventually to
+ ;; duplicate declarations as reported in
+ ;; <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59217>.
+ ("gmp-native" ,gmp)
+ ("mpfr-native" ,mpfr)
+ ("mpc-native" ,mpc)
+ ,@(package-native-inputs gcc-4.8))
+ (package-native-inputs gcc-4.8))))))
(define %gcc-stripped
;; The subset of GCC files needed for bootstrap.
- (package (inherit gcc-4.7)
+ (package (inherit gcc-4.8)
(name "gcc-stripped")
(build-system trivial-build-system)
(source #f)
+ (outputs '("out")) ;only one output
(arguments
`(#:modules ((guix build utils))
#:builder
(let* ((out (assoc-ref %outputs "out"))
(bindir (string-append out "/bin"))
(libdir (string-append out "/lib"))
+ (includedir (string-append out "/include"))
(libexecdir (string-append out "/libexec"))
(gcc (assoc-ref %build-inputs "gcc")))
(copy-recursively (string-append gcc "/bin") bindir)
libexecdir)
(for-each remove-store-references
(find-files libexecdir ".*"))
- #t))))
+
+ ;; Starting from GCC 4.8, helper programs built natively
+ ;; (‘genchecksum’, ‘gcc-nm’, etc.) rely on C++ headers.
+ (copy-recursively (string-append gcc "/include/c++")
+ (string-append includedir "/c++"))
+
+ ;; For native builds, check whether the binaries actually work.
+ ,(if (%current-target-system)
+ '#t
+ '(every (lambda (prog)
+ (zero? (system* (string-append gcc "/bin/" prog)
+ "--version")))
+ '("gcc" "g++" "cpp")))))))
(inputs `(("gcc" ,%gcc-static)))))
(define %guile-static
;; A statically-linked Guile that is relocatable--i.e., it can search
;; .scm and .go files relative to its installation directory, rather
;; than in hard-coded configure-time paths.
- (let* ((libgc (package (inherit libgc)
- (arguments
- ;; Make it so that we don't rely on /proc. This is
- ;; especially useful in an initrd run before /proc is
- ;; mounted.
- '(#:configure-flags '("CPPFLAGS=-DUSE_LIBC_PRIVATES")))))
+ (let* ((patches (cons* (search-patch "guile-relocatable.patch")
+ (search-patch "guile-default-utf8.patch")
+ (search-patch "guile-linux-syscalls.patch")
+ (origin-patches (package-source guile-2.0))))
+ (source (origin (inherit (package-source guile-2.0))
+ (patches patches)))
(guile (package (inherit guile-2.0)
(name (string-append (package-name guile-2.0) "-static"))
- (inputs
- `(("patch/relocatable"
- ,(search-patch "guile-relocatable.patch"))
- ("patch/utf8"
- ,(search-patch "guile-default-utf8.patch"))
- ("patch/syscalls"
- ,(search-patch "guile-linux-syscalls.patch"))
- ,@(package-inputs guile-2.0)))
+ (source source)
+ (synopsis "Statically-linked and relocatable Guile")
+
+ ;; Remove the 'debug' output (see above for the reason.)
+ (outputs (delete "debug" (package-outputs guile-2.0)))
+
(propagated-inputs
`(("bdw-gc" ,libgc)
,@(alist-delete "bdw-gc"
" -ldl\n"))))
%standard-phases)
- ;; Allow Guile to be relocated, as is needed during
- ;; bootstrap.
- #:patches
- (list (assoc-ref %build-inputs "patch/relocatable")
- (assoc-ref %build-inputs "patch/utf8")
- (assoc-ref %build-inputs "patch/syscalls"))
-
;; There are uses of `dynamic-link' in
;; {foreign,coverage}.test that don't fly here.
#:tests? #f)))))
- (package-with-explicit-inputs (static-package guile)
- %standard-inputs-with-relocatable-glibc
- (current-source-location))))
+ (package-with-relocatable-glibc (static-package guile))))
(define %guile-static-stripped
;; A stripped static Guile binary, for use during bootstrap.
(let ()
(use-modules (guix build utils))
- (let ((in (assoc-ref %build-inputs "guile"))
- (out (assoc-ref %outputs "out")))
+ (let* ((in (assoc-ref %build-inputs "guile"))
+ (out (assoc-ref %outputs "out"))
+ (guile1 (string-append in "/bin/guile"))
+ (guile2 (string-append out "/bin/guile")))
(mkdir-p (string-append out "/share/guile/2.0"))
(copy-recursively (string-append in "/share/guile/2.0")
(string-append out "/share/guile/2.0"))
(string-append out "/lib/guile/2.0/ccache"))
(mkdir (string-append out "/bin"))
- (copy-file (string-append in "/bin/guile")
- (string-append out "/bin/guile"))
- (remove-store-references (string-append out "/bin/guile"))
- #t))))
- (inputs `(("guile" ,%guile-static)))))
+ (copy-file guile1 guile2)
+
+ ;; Does the relocated Guile work?
+ (and ,(if (%current-target-system)
+ #t
+ '(zero? (system* guile2 "--version")))
+ (begin
+ ;; Strip store references.
+ (remove-store-references guile2)
+
+ ;; Does the stripped Guile work? If it aborts, it could be
+ ;; that it tries to open iconv descriptors and fails because
+ ;; libc's iconv data isn't available (see
+ ;; `guile-default-utf8.patch'.)
+ ,(if (%current-target-system)
+ #t
+ '(zero? (system* guile2 "--version")))))))))
+ (inputs `(("guile" ,%guile-static)))
+ (outputs '("out"))
+ (synopsis "Minimal statically-linked and relocatable Guile")))
(define (tarball-package pkg)
"Return a package containing a tarball of PKG."
(location (source-properties->location (current-source-location)))
(name (string-append (package-name pkg) "-tarball"))
(build-system trivial-build-system)
- (inputs `(("tar" ,tar)
- ("xz" ,xz)
- ("input" ,pkg)))
+ (native-inputs `(("tar" ,tar)
+ ("xz" ,xz)))
+ (inputs `(("input" ,pkg)))
(arguments
(let ((name (package-name pkg))
(version (package-version pkg)))
(zero? (system* "tar" "cJvf"
(string-append out "/"
,name "-" ,version
- "-" ,(%current-system)
+ "-"
+ ,(or (%current-target-system)
+ (%current-system))
".tar.xz")
"."))))))))))