1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
4 ;;; Copyright © 2017 Efraim Flashner <efraim@flashner.co.il>
6 ;;; This file is part of GNU Guix.
8 ;;; GNU Guix is free software; you can redistribute it and/or modify it
9 ;;; under the terms of the GNU General Public License as published by
10 ;;; the Free Software Foundation; either version 3 of the License, or (at
11 ;;; your option) any later version.
13 ;;; GNU Guix is distributed in the hope that it will be useful, but
14 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;;; GNU General Public License for more details.
18 ;;; You should have received a copy of the GNU General Public License
19 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21 (define-module (gnu packages bootstrap)
22 #:use-module (guix licenses)
23 #:use-module (gnu packages)
24 #:use-module (guix packages)
25 #:use-module (guix download)
26 #:use-module (guix build-system)
27 #:use-module (guix build-system gnu)
28 #:use-module (guix build-system trivial)
29 #:use-module ((guix store) #:select (add-to-store add-text-to-store))
30 #:use-module ((guix derivations) #:select (derivation))
31 #:use-module ((guix utils) #:select (gnu-triplet->nix-system))
32 #:use-module ((guix build utils) #:select (elf-file?))
33 #:use-module (guix memoization)
34 #:use-module (srfi srfi-1)
35 #:use-module (srfi srfi-26)
36 #:use-module (ice-9 match)
37 #:export (bootstrap-origin
38 package-with-bootstrap-guile
42 %bootstrap-coreutils&co
50 ;;; Pre-built packages that are used to bootstrap the
51 ;;; distribution--i.e., to build all the core packages from scratch.
58 ;;; Helper procedures.
61 (define (bootstrap-origin source)
62 "Return a variant of SOURCE, an <origin> instance, whose method uses
63 %BOOTSTRAP-GUILE to do its job."
65 (lambda* (url hash-algo hash
66 #:optional name #:key system)
67 (fetch url hash-algo hash name
68 #:guile %bootstrap-guile
71 (define %bootstrap-patch-inputs
72 ;; Packages used when an <origin> has a non-empty 'patches' field.
73 `(("tar" ,%bootstrap-coreutils&co)
74 ("xz" ,%bootstrap-coreutils&co)
75 ("bzip2" ,%bootstrap-coreutils&co)
76 ("gzip" ,%bootstrap-coreutils&co)
77 ("patch" ,%bootstrap-coreutils&co)))
79 (let ((orig-method (origin-method source)))
80 (origin (inherit source)
81 (method (cond ((eq? orig-method url-fetch)
84 (patch-guile %bootstrap-guile)
85 (patch-inputs %bootstrap-patch-inputs)
87 ;; Patches can be origins as well, so process them.
88 (patches (map (match-lambda
90 (bootstrap-origin patch))
92 (origin-patches source))))))
94 (define* (package-from-tarball name source program-to-test description
96 "Return a package that correspond to the extraction of SOURCE.
97 PROGRAM-TO-TEST is a program to run after extraction of SOURCE, to
98 check whether everything is alright. If SNIPPET is provided, it is
99 evaluated after extracting SOURCE. SNIPPET should return true if
100 successful, or false to signal an error."
104 (build-system trivial-build-system)
106 `(#:guile ,%bootstrap-guile
107 #:modules ((guix build utils))
109 (let ((out (assoc-ref %outputs "out"))
110 (tar (assoc-ref %build-inputs "tar"))
111 (xz (assoc-ref %build-inputs "xz"))
112 (tarball (assoc-ref %build-inputs "tarball")))
113 (use-modules (guix build utils))
116 (copy-file tarball "binaries.tar.xz")
117 (system* xz "-d" "binaries.tar.xz")
118 (let ((builddir (getcwd)))
119 (with-directory-excursion out
120 (and (zero? (system* tar "xvf"
121 (string-append builddir "/binaries.tar")))
122 ,@(if snippet (list snippet) '())
123 (zero? (system* (string-append "bin/" ,program-to-test)
126 `(("tar" ,(search-bootstrap-binary "tar" (%current-system)))
127 ("xz" ,(search-bootstrap-binary "xz" (%current-system)))
128 ("tarball" ,(bootstrap-origin (source (%current-system))))))
130 (synopsis description)
131 (description description)
135 (define package-with-bootstrap-guile
137 "Return a variant of P such that all its origins are fetched with
139 (define rewritten-input
141 ((name (? origin? o))
142 `(,name ,(bootstrap-origin o)))
143 ((name (? package? p) sub-drvs ...)
144 `(,name ,(package-with-bootstrap-guile p) ,@sub-drvs))
148 (source (match (package-source p)
149 ((? origin? o) (bootstrap-origin o))
151 (inputs (map rewritten-input
153 (native-inputs (map rewritten-input
154 (package-native-inputs p)))
155 (propagated-inputs (map rewritten-input
156 (package-propagated-inputs p)))
157 (replacement (and=> (package-replacement p)
158 package-with-bootstrap-guile)))))
160 (define* (glibc-dynamic-linker
161 #:optional (system (or (and=> (%current-target-system)
162 gnu-triplet->nix-system)
164 "Return the name of Glibc's dynamic linker for SYSTEM."
165 (cond ((string=? system "x86_64-linux") "/lib/ld-linux-x86-64.so.2")
166 ((string=? system "i686-linux") "/lib/ld-linux.so.2")
167 ((string=? system "armhf-linux") "/lib/ld-linux-armhf.so.3")
168 ((string=? system "mips64el-linux") "/lib/ld.so.1")
169 ((string=? system "i586-gnu") "/lib/ld.so.1")
170 ((string=? system "i686-gnu") "/lib/ld.so.1")
171 ((string=? system "aarch64-linux") "/lib/ld-linux-aarch64.so.1")
172 ((string=? system "powerpc-linux") "/lib/ld.so.1")
173 ((string=? system "alpha-linux") "/lib/ld-linux.so.2")
175 ;; XXX: This one is used bare-bones, without a libc, so add a case
176 ;; here just so we can keep going.
177 ((string=? system "arm-eabi") "no-ld.so")
178 ((string=? system "xtensa-elf") "no-ld.so")
179 ((string=? system "avr") "no-ld.so")
180 ((string=? system "propeller-elf") "no-ld.so")
181 ((string=? system "i686-mingw") "no-ld.so")
182 ((string=? system "vc4-elf") "no-ld.so")
184 (else (error "dynamic linker name not known for this system"
189 ;;; Bootstrap packages.
192 (define* (raw-build store name inputs
193 #:key outputs system search-paths
195 (define (->store file)
196 (add-to-store store file #t "sha256"
197 (or (search-bootstrap-binary file
199 (error "bootstrap binary not found"
202 (let* ((tar (->store "tar"))
204 (mkdir (->store "mkdir"))
205 (bash (->store "bash"))
206 (guile (->store (match system
208 "guile-2.0.11.tar.xz")
210 "guile-2.0.14.tar.xz")
212 "guile-2.0.9.tar.xz"))))
213 ;; The following code, run by the bootstrap guile after it is
214 ;; unpacked, creates a wrapper for itself to set its load path.
215 ;; This replaces the previous non-portable method based on
216 ;; reading the /proc/self/exe symlink.
219 (use-modules (ice-9 match))
220 (match (command-line)
222 (let ((bin-dir (string-append out "/bin"))
223 (guile (string-append out "/bin/guile"))
224 (guile-real (string-append out "/bin/.guile-real"))
225 ;; We must avoid using a bare dollar sign in this code,
226 ;; because it would be interpreted by the shell.
227 (dollar (string (integer->char 36))))
228 (chmod bin-dir #o755)
229 (rename-file guile guile-real)
230 (call-with-output-file guile
234 export GUILE_SYSTEM_PATH=~a/share/guile/2.0
235 export GUILE_SYSTEM_COMPILED_PATH=~a/lib/guile/2.0/ccache
236 exec -a \"~a0\" ~a \"~a@\"\n"
237 bash out out dollar guile-real dollar)))
239 (chmod bin-dir #o555))))))
241 (add-text-to-store store
242 "build-bootstrap-guile.sh"
244 echo \"unpacking bootstrap Guile to '$out'...\"
249 # Use the bootstrap guile to create its own wrapper to set the load path.
250 GUILE_SYSTEM_PATH=$out/share/guile/2.0 \
251 GUILE_SYSTEM_COMPILED_PATH=$out/lib/guile/2.0/ccache \
252 $out/bin/guile -c ~s $out ~a
255 $out/bin/guile --version~%"
257 (format #f "~s" make-guile-wrapper)
259 (list mkdir xz guile tar bash))))
260 (derivation store name
263 #:inputs `((,bash) (,builder)))))
265 (define* (make-raw-bag name
266 #:key source inputs native-inputs outputs
271 (build-inputs inputs)
274 (define %bootstrap-guile
275 ;; The Guile used to run the build scripts of the initial derivations.
276 ;; It is just unpacked from a tarball containing a pre-built binary.
277 ;; This is typically built using %GUILE-BOOTSTRAP-TARBALL below.
279 ;; XXX: Would need libc's `libnss_files2.so' for proper `getaddrinfo'
280 ;; support (for /etc/services).
281 (let ((raw (build-system
283 (description "Raw build system with direct store access")
284 (lower make-raw-bag))))
286 (name "guile-bootstrap")
290 (synopsis "Bootstrap Guile")
291 (description "Pre-built Guile for bootstrapping purposes.")
295 (define %bootstrap-base-urls
296 ;; This is where the initial binaries come from.
297 '("ftp://alpha.gnu.org/gnu/guix/bootstrap"
298 "http://alpha.gnu.org/gnu/guix/bootstrap"
299 "http://www.fdn.fr/~lcourtes/software/guix/packages"
300 "http://flashner.co.il/guix/bootstrap"))
302 (define %bootstrap-coreutils&co
303 (package-from-tarball "bootstrap-binaries"
307 (uri (map (cut string-append <> "/" system
310 "/20150101/static-binaries.tar.xz")
312 "/20170217/static-binaries.tar.xz")
314 "/20131110/static-binaries.tar.xz")))
315 %bootstrap-base-urls))
320 "0c533p9dhczzcsa1117gmfq3pc8w362g4mx84ik36srpr7cx2bg4"))
323 "0s5b3jb315n13m1k8095l0a5hfrsz8g0fv1b6riyc5hnxqyphlak"))
326 "0gf0fn2kbpxkjixkmx5f4z6hv6qpmgixl69zgg74dbsfdfj8jdv5"))
329 "18dfiq6c6xhsdpbidigw6480wh0vdgsxqq3xindq4lpdgqlccpfh"))
332 "072y4wyfsj1bs80r6vbybbafy8ya4vfy7qj25dklwk97m6g71753"))))))
333 "fgrep" ; the program to test
334 "Bootstrap binaries of Coreutils, Awk, etc."
336 '(let ((path (list (string-append (getcwd) "/bin"))))
338 (patch-shebang "bin/egrep" path)
339 (patch-shebang "bin/fgrep" path)
340 ;; Starting with grep@2.25 'egrep' and 'fgrep' are shell files
341 ;; that call 'grep'. If the bootstrap 'egrep' and 'fgrep'
342 ;; are not binaries then patch them to execute 'grep' via its
343 ;; absolute file name instead of searching for it in $PATH.
344 (if (not (elf-file? "bin/egrep"))
345 (substitute* '("bin/egrep" "bin/fgrep")
346 (("^exec grep") (string-append (getcwd) "/bin/grep"))))
350 (define %bootstrap-binutils
351 (package-from-tarball "binutils-bootstrap"
355 (uri (map (cut string-append <> "/" system
358 "/20150101/binutils-2.25.tar.xz")
360 "/20170217/binutils-2.27.tar.xz")
362 "/20131110/binutils-2.23.2.tar.xz")))
363 %bootstrap-base-urls))
368 "1j5yivz7zkjqfsfmxzrrrffwyayjqyfxgpi89df0w4qziqs2dg20"))
371 "14jgwf9gscd7l2pnz610b1zia06dvcm2qyzvni31b8zpgmcai2v9"))
374 "1v7dj6bzn6m36f20gw31l99xaabq4xrhrx3gwqkhhig0mdlmr69q"))
377 "111s7ilfiby033rczc71797xrmaa3qlv179wdvsaq132pd51xv3n"))
380 "1x8kkhcxmfyzg1ddpz2pxs6fbdl6412r7x0nzbmi5n7mj8zw2gy7"))))))
381 "ld" ; the program to test
382 "Bootstrap binaries of the GNU Binutils"))
384 (define %bootstrap-glibc
387 (name "glibc-bootstrap")
390 (build-system trivial-build-system)
392 `(#:guile ,%bootstrap-guile
393 #:modules ((guix build utils))
395 (let ((out (assoc-ref %outputs "out"))
396 (tar (assoc-ref %build-inputs "tar"))
397 (xz (assoc-ref %build-inputs "xz"))
398 (tarball (assoc-ref %build-inputs "tarball")))
399 (use-modules (guix build utils))
402 (copy-file tarball "binaries.tar.xz")
403 (system* xz "-d" "binaries.tar.xz")
404 (let ((builddir (getcwd)))
405 (with-directory-excursion out
407 (string-append builddir
411 ;; Patch libc.so so it refers to the right path.
412 (substitute* "lib/libc.so"
413 (("/[^ ]+/lib/(libc|ld)" _ prefix)
414 (string-append out "/lib/" prefix))))))))
416 `(("tar" ,(search-bootstrap-binary "tar" (%current-system)))
417 ("xz" ,(search-bootstrap-binary "xz" (%current-system)))
418 ("tarball" ,(bootstrap-origin
421 (uri (map (cut string-append <> "/" (%current-system)
422 (match (%current-system)
424 "/20150101/glibc-2.20.tar.xz")
426 "/20170217/glibc-2.25.tar.xz")
428 "/20131110/glibc-2.18.tar.xz")))
429 %bootstrap-base-urls))
431 (match (%current-system)
434 "0jlqrgavvnplj1b083s20jj9iddr4lzfvwybw5xrcis9spbfzk7v"))
437 "1hgrccw1zqdc7lvgivwa54d9l3zsim5pqm0dykxg0z522h6gr05w"))
440 "18cmgvpllqfpn6khsmivqib7ys8ymnq0hdzi3qp24prik0ykz8gn"))
443 "07nx3x8598i2924rjnlrncg6rm61c9bmcczbbcpbx0fb742nvv5c"))
446 "0k97a3whzx3apsi9n2cbsrr79ad6lh00klxph9hw4fqyp1abkdsg")))))))))
447 (synopsis "Bootstrap binaries and headers of the GNU C Library")
448 (description synopsis)
452 (define %bootstrap-gcc
453 ;; The initial GCC. Uses binaries from a tarball typically built by
454 ;; %GCC-BOOTSTRAP-TARBALL.
456 (name "gcc-bootstrap")
459 (build-system trivial-build-system)
461 `(#:guile ,%bootstrap-guile
462 #:modules ((guix build utils))
464 (let ((out (assoc-ref %outputs "out"))
465 (tar (assoc-ref %build-inputs "tar"))
466 (xz (assoc-ref %build-inputs "xz"))
467 (bash (assoc-ref %build-inputs "bash"))
468 (libc (assoc-ref %build-inputs "libc"))
469 (tarball (assoc-ref %build-inputs "tarball")))
470 (use-modules (guix build utils)
474 (copy-file tarball "binaries.tar.xz")
475 (system* xz "-d" "binaries.tar.xz")
476 (let ((builddir (getcwd))
477 (bindir (string-append out "/bin")))
478 (with-directory-excursion out
480 (string-append builddir "/binaries.tar")))
482 (with-directory-excursion bindir
484 (rename-file "gcc" ".gcc-wrapped")
485 (call-with-output-file "gcc"
488 exec ~a/bin/.gcc-wrapped -B~a/lib \
489 -Wl,-rpath -Wl,~a/lib \
490 -Wl,-dynamic-linker -Wl,~a/~a \"$@\"~%"
493 ,(glibc-dynamic-linker))))
495 (chmod "gcc" #o555))))))
497 `(("tar" ,(search-bootstrap-binary "tar" (%current-system)))
498 ("xz" ,(search-bootstrap-binary "xz" (%current-system)))
499 ("bash" ,(search-bootstrap-binary "bash" (%current-system)))
500 ("libc" ,%bootstrap-glibc)
501 ("tarball" ,(bootstrap-origin
504 (uri (map (cut string-append <> "/" (%current-system)
505 (match (%current-system)
507 "/20150101/gcc-4.8.4.tar.xz")
509 "/20170217/gcc-5.4.0.tar.xz")
511 "/20131110/gcc-4.8.2.tar.xz")))
512 %bootstrap-base-urls))
514 (match (%current-system)
517 "17ga4m6195n4fnbzdkmik834znkhs53nkypp6557pl1ps7dgqbls"))
520 "150c1arrf2k8vfy6dpxh59vcgs4p1bgiz2av5m19dynpks7rjnyw"))
523 "0ghz825yzp43fxw53kd6afm8nkz16f7dxi9xi40bfwc8x3nbbr8v"))
526 "1ar3vdzyqbfm0z36kmvazvfswxhcihlacl2dzdjgiq25cqnq9ih1"))
529 "1m5miqkyng45l745n0sfafdpjkqv9225xf44jqkygwsipj2cv9ks")))))))))
531 (list (search-path-specification
533 (files '("include")))
534 (search-path-specification
535 (variable "LIBRARY_PATH")
536 (files '("lib" "lib64")))))
537 (synopsis "Bootstrap binaries of the GNU Compiler Collection")
538 (description synopsis)
542 (define %bootstrap-inputs
543 ;; The initial, pre-built inputs. From now on, we can start building our
545 `(("libc" ,%bootstrap-glibc)
546 ("gcc" ,%bootstrap-gcc)
547 ("binutils" ,%bootstrap-binutils)
548 ("coreutils&co" ,%bootstrap-coreutils&co)
550 ;; In gnu-build-system.scm, we rely on the availability of Bash.
551 ("bash" ,%bootstrap-coreutils&co)))
553 ;;; bootstrap.scm ends here