1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2014, 2015, 2018 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)
30 #:select (run-with-store add-to-store add-text-to-store))
31 #:use-module ((guix derivations)
32 #:select (derivation derivation->output-path))
33 #:use-module ((guix utils) #:select (gnu-triplet->nix-system))
34 #:use-module (guix memoization)
35 #:use-module (srfi srfi-1)
36 #:use-module (srfi srfi-26)
37 #:use-module (ice-9 match)
38 #:export (bootstrap-origin
39 package-with-bootstrap-guile
42 bootstrap-guile-origin
45 %bootstrap-coreutils&co
53 ;;; Pre-built packages that are used to bootstrap the
54 ;;; distribution--i.e., to build all the core packages from scratch.
61 ;;; Helper procedures.
64 (define (bootstrap-origin source)
65 "Return a variant of SOURCE, an <origin> instance, whose method uses
66 %BOOTSTRAP-GUILE to do its job."
68 (lambda* (url hash-algo hash
69 #:optional name #:key system)
70 (fetch url hash-algo hash name
71 #:guile %bootstrap-guile
74 (define %bootstrap-patch-inputs
75 ;; Packages used when an <origin> has a non-empty 'patches' field.
76 `(("tar" ,%bootstrap-coreutils&co)
77 ("xz" ,%bootstrap-coreutils&co)
78 ("bzip2" ,%bootstrap-coreutils&co)
79 ("gzip" ,%bootstrap-coreutils&co)
80 ("patch" ,%bootstrap-coreutils&co)))
82 (let ((orig-method (origin-method source)))
83 (origin (inherit source)
84 (method (cond ((eq? orig-method url-fetch)
87 (patch-guile %bootstrap-guile)
88 (patch-inputs %bootstrap-patch-inputs)
90 ;; Patches can be origins as well, so process them.
91 (patches (map (match-lambda
93 (bootstrap-origin patch))
95 (origin-patches source))))))
97 (define* (package-from-tarball name source program-to-test description
99 "Return a package that correspond to the extraction of SOURCE.
100 PROGRAM-TO-TEST is a program to run after extraction of SOURCE, to check
101 whether everything is alright. If SNIPPET is provided, it is evaluated after
102 extracting SOURCE. SNIPPET should raise an exception to signal an error; its
103 return value is ignored."
107 (build-system trivial-build-system)
109 `(#:guile ,%bootstrap-guile
110 #:modules ((guix build utils))
112 (let ((out (assoc-ref %outputs "out"))
113 (tar (assoc-ref %build-inputs "tar"))
114 (xz (assoc-ref %build-inputs "xz"))
115 (tarball (assoc-ref %build-inputs "tarball")))
116 (use-modules (guix build utils))
119 (copy-file tarball "binaries.tar.xz")
120 (invoke xz "-d" "binaries.tar.xz")
121 (let ((builddir (getcwd)))
122 (with-directory-excursion out
124 (string-append builddir "/binaries.tar"))
125 ,@(if snippet (list snippet) '())
126 (invoke (string-append "bin/" ,program-to-test)
129 `(("tar" ,(search-bootstrap-binary "tar" (%current-system)))
130 ("xz" ,(search-bootstrap-binary "xz" (%current-system)))
131 ("tarball" ,(bootstrap-origin (source (%current-system))))))
133 (synopsis description)
134 (description description)
138 (define package-with-bootstrap-guile
140 "Return a variant of P such that all its origins are fetched with
142 (define rewritten-input
144 ((name (? origin? o))
145 `(,name ,(bootstrap-origin o)))
146 ((name (? package? p) sub-drvs ...)
147 `(,name ,(package-with-bootstrap-guile p) ,@sub-drvs))
151 (source (match (package-source p)
152 ((? origin? o) (bootstrap-origin o))
154 (inputs (map rewritten-input
156 (native-inputs (map rewritten-input
157 (package-native-inputs p)))
158 (propagated-inputs (map rewritten-input
159 (package-propagated-inputs p)))
160 (replacement (and=> (package-replacement p)
161 package-with-bootstrap-guile)))))
163 (define* (glibc-dynamic-linker
164 #:optional (system (or (and=> (%current-target-system)
165 gnu-triplet->nix-system)
167 "Return the name of Glibc's dynamic linker for SYSTEM."
168 ;; See the 'SYSDEP_KNOWN_INTERPRETER_NAMES' cpp macro in libc.
169 (cond ((string=? system "x86_64-linux") "/lib/ld-linux-x86-64.so.2")
170 ((string=? system "i686-linux") "/lib/ld-linux.so.2")
171 ((string=? system "armhf-linux") "/lib/ld-linux-armhf.so.3")
172 ((string=? system "mips64el-linux") "/lib/ld.so.1")
173 ((string=? system "i586-gnu") "/lib/ld.so.1")
174 ((string=? system "i686-gnu") "/lib/ld.so.1")
175 ((string=? system "aarch64-linux") "/lib/ld-linux-aarch64.so.1")
176 ((string=? system "powerpc-linux") "/lib/ld.so.1")
177 ((string=? system "powerpc64le-linux") "/lib/ld64.so.2")
178 ((string=? system "alpha-linux") "/lib/ld-linux.so.2")
179 ((string=? system "s390x-linux") "/lib/ld64.so.1")
181 ;; XXX: This one is used bare-bones, without a libc, so add a case
182 ;; here just so we can keep going.
183 ((string=? system "arm-eabi") "no-ld.so")
184 ((string=? system "xtensa-elf") "no-ld.so")
185 ((string=? system "avr") "no-ld.so")
186 ((string=? system "propeller-elf") "no-ld.so")
187 ((string=? system "i686-mingw") "no-ld.so")
188 ((string=? system "vc4-elf") "no-ld.so")
190 (else (error "dynamic linker name not known for this system"
195 ;;; Bootstrap packages.
198 (define %bootstrap-base-urls
199 ;; This is where the initial binaries come from.
200 '("https://alpha.gnu.org/gnu/guix/bootstrap"
201 "http://alpha.gnu.org/gnu/guix/bootstrap"
202 "ftp://alpha.gnu.org/gnu/guix/bootstrap"
203 "http://www.fdn.fr/~lcourtes/software/guix/packages"
204 "http://flashner.co.il/guix/bootstrap"))
206 (define (bootstrap-guile-url-path system)
207 "Return the URI for FILE."
208 (string-append "/" system
211 "/20170217/guile-2.0.14.tar.xz")
213 "/20150101/guile-2.0.11.tar.xz")
215 "/20131110/guile-2.0.9.tar.xz"))))
217 (define (bootstrap-guile-hash system)
218 "Return the SHA256 hash of the Guile bootstrap tarball for SYSTEM."
221 (base32 "1w2p5zyrglzzniqgvyn1b55vprfzhgk8vzbzkkbdgl5248si0yq3"))
223 (base32 "0im800m30abgh7msh331pcbjvb4n02smz5cfzf1srv0kpx3csmxp"))
225 (base32 "0fzp93lvi0hn54acc0fpvhc7bvl0yc853k62l958cihk03q80ilr"))
227 (base32 "1mi3brl7l58aww34rawhvja84xc7l1b4hmwdmc36fp9q9mfx0lg5"))
229 (base32 "1giy2aprjmn5fp9c4s9r125fljw4wv6ixy5739i5bffw4jgr0f9r"))))
231 (define (bootstrap-guile-origin system)
232 "Return an <origin> object for the Guile tarball of SYSTEM."
235 (uri (map (cute string-append <> (bootstrap-guile-url-path system))
236 %bootstrap-base-urls))
237 (sha256 (bootstrap-guile-hash system))))
239 (define (download-bootstrap-guile store system)
240 "Return a derivation that downloads the bootstrap Guile tarball for SYSTEM."
241 (let* ((path (bootstrap-guile-url-path system))
242 (base (basename path))
243 (urls (map (cut string-append <> path) %bootstrap-base-urls)))
244 (run-with-store store
245 (url-fetch urls 'sha256 (bootstrap-guile-hash system)
248 (define* (raw-build store name inputs
249 #:key outputs system search-paths
251 (define (->store file)
252 (add-to-store store file #t "sha256"
253 (or (search-bootstrap-binary file
255 (error "bootstrap binary not found"
258 (let* ((tar (->store "tar"))
260 (mkdir (->store "mkdir"))
261 (bash (->store "bash"))
262 (guile (download-bootstrap-guile store system))
263 ;; The following code, run by the bootstrap guile after it is
264 ;; unpacked, creates a wrapper for itself to set its load path.
265 ;; This replaces the previous non-portable method based on
266 ;; reading the /proc/self/exe symlink.
269 (use-modules (ice-9 match))
270 (match (command-line)
272 (let ((bin-dir (string-append out "/bin"))
273 (guile (string-append out "/bin/guile"))
274 (guile-real (string-append out "/bin/.guile-real"))
275 ;; We must avoid using a bare dollar sign in this code,
276 ;; because it would be interpreted by the shell.
277 (dollar (string (integer->char 36))))
278 (chmod bin-dir #o755)
279 (rename-file guile guile-real)
280 (call-with-output-file guile
284 export GUILE_SYSTEM_PATH=~a/share/guile/2.0
285 export GUILE_SYSTEM_COMPILED_PATH=~a/lib/guile/2.0/ccache
286 exec -a \"~a0\" ~a \"~a@\"\n"
287 bash out out dollar guile-real dollar)))
289 (chmod bin-dir #o555))))))
291 (add-text-to-store store
292 "build-bootstrap-guile.sh"
294 echo \"unpacking bootstrap Guile to '$out'...\"
297 ~a -dc < $GUILE_TARBALL | ~a xv
299 # Use the bootstrap guile to create its own wrapper to set the load path.
300 GUILE_SYSTEM_PATH=$out/share/guile/2.0 \
301 GUILE_SYSTEM_COMPILED_PATH=$out/lib/guile/2.0/ccache \
302 $out/bin/guile -c ~s $out ~a
305 $out/bin/guile --version~%"
307 (format #f "~s" make-guile-wrapper)
309 (list mkdir xz tar bash))))
310 (derivation store name
313 #:inputs `((,bash) (,builder) (,guile))
314 #:env-vars `(("GUILE_TARBALL"
315 . ,(derivation->output-path guile))))))
317 (define* (make-raw-bag name
318 #:key source inputs native-inputs outputs
323 (build-inputs inputs)
326 (define %bootstrap-guile
327 ;; The Guile used to run the build scripts of the initial derivations.
328 ;; It is just unpacked from a tarball containing a pre-built binary.
329 ;; This is typically built using %GUILE-BOOTSTRAP-TARBALL below.
331 ;; XXX: Would need libc's `libnss_files2.so' for proper `getaddrinfo'
332 ;; support (for /etc/services).
333 (let ((raw (build-system
335 (description "Raw build system with direct store access")
336 (lower make-raw-bag))))
338 (name "guile-bootstrap")
342 (synopsis "Bootstrap Guile")
343 (description "Pre-built Guile for bootstrapping purposes.")
347 (define %bootstrap-coreutils&co
348 (package-from-tarball "bootstrap-binaries"
352 (uri (map (cut string-append <> "/" system
355 "/20150101/static-binaries.tar.xz")
357 "/20170217/static-binaries.tar.xz")
359 "/20131110/static-binaries.tar.xz")))
360 %bootstrap-base-urls))
365 "0c533p9dhczzcsa1117gmfq3pc8w362g4mx84ik36srpr7cx2bg4"))
368 "0s5b3jb315n13m1k8095l0a5hfrsz8g0fv1b6riyc5hnxqyphlak"))
371 "0gf0fn2kbpxkjixkmx5f4z6hv6qpmgixl69zgg74dbsfdfj8jdv5"))
374 "18dfiq6c6xhsdpbidigw6480wh0vdgsxqq3xindq4lpdgqlccpfh"))
377 "072y4wyfsj1bs80r6vbybbafy8ya4vfy7qj25dklwk97m6g71753"))))))
378 "fgrep" ; the program to test
379 "Bootstrap binaries of Coreutils, Awk, etc."
381 '(let ((path (list (string-append (getcwd) "/bin"))))
383 (patch-shebang "bin/egrep" path)
384 (patch-shebang "bin/fgrep" path)
385 ;; Starting with grep@2.25 'egrep' and 'fgrep' are shell files
386 ;; that call 'grep'. If the bootstrap 'egrep' and 'fgrep'
387 ;; are not binaries then patch them to execute 'grep' via its
388 ;; absolute file name instead of searching for it in $PATH.
389 (if (not (elf-file? "bin/egrep"))
390 (substitute* '("bin/egrep" "bin/fgrep")
391 (("^exec grep") (string-append (getcwd) "/bin/grep"))))
392 (chmod "bin" #o555))))
394 (define %bootstrap-binutils
395 (package-from-tarball "binutils-bootstrap"
399 (uri (map (cut string-append <> "/" system
402 "/20150101/binutils-2.25.tar.xz")
404 "/20170217/binutils-2.27.tar.xz")
406 "/20131110/binutils-2.23.2.tar.xz")))
407 %bootstrap-base-urls))
412 "1j5yivz7zkjqfsfmxzrrrffwyayjqyfxgpi89df0w4qziqs2dg20"))
415 "14jgwf9gscd7l2pnz610b1zia06dvcm2qyzvni31b8zpgmcai2v9"))
418 "1v7dj6bzn6m36f20gw31l99xaabq4xrhrx3gwqkhhig0mdlmr69q"))
421 "111s7ilfiby033rczc71797xrmaa3qlv179wdvsaq132pd51xv3n"))
424 "1x8kkhcxmfyzg1ddpz2pxs6fbdl6412r7x0nzbmi5n7mj8zw2gy7"))))))
425 "ld" ; the program to test
426 "Bootstrap binaries of the GNU Binutils"))
428 (define %bootstrap-glibc
431 (name "glibc-bootstrap")
434 (build-system trivial-build-system)
436 `(#:guile ,%bootstrap-guile
437 #:modules ((guix build utils))
439 (let ((out (assoc-ref %outputs "out"))
440 (tar (assoc-ref %build-inputs "tar"))
441 (xz (assoc-ref %build-inputs "xz"))
442 (tarball (assoc-ref %build-inputs "tarball")))
443 (use-modules (guix build utils))
446 (copy-file tarball "binaries.tar.xz")
447 (invoke xz "-d" "binaries.tar.xz")
448 (let ((builddir (getcwd)))
449 (with-directory-excursion out
451 (string-append builddir
455 ;; Patch libc.so so it refers to the right path.
456 (substitute* "lib/libc.so"
457 (("/[^ ]+/lib/(libc|ld)" _ prefix)
458 (string-append out "/lib/" prefix)))
462 `(("tar" ,(search-bootstrap-binary "tar" (%current-system)))
463 ("xz" ,(search-bootstrap-binary "xz" (%current-system)))
464 ("tarball" ,(bootstrap-origin
467 (uri (map (cut string-append <> "/" (%current-system)
468 (match (%current-system)
470 "/20150101/glibc-2.20.tar.xz")
472 "/20170217/glibc-2.25.tar.xz")
474 "/20131110/glibc-2.18.tar.xz")))
475 %bootstrap-base-urls))
477 (match (%current-system)
480 "0jlqrgavvnplj1b083s20jj9iddr4lzfvwybw5xrcis9spbfzk7v"))
483 "1hgrccw1zqdc7lvgivwa54d9l3zsim5pqm0dykxg0z522h6gr05w"))
486 "18cmgvpllqfpn6khsmivqib7ys8ymnq0hdzi3qp24prik0ykz8gn"))
489 "07nx3x8598i2924rjnlrncg6rm61c9bmcczbbcpbx0fb742nvv5c"))
492 "0k97a3whzx3apsi9n2cbsrr79ad6lh00klxph9hw4fqyp1abkdsg")))))))))
493 (synopsis "Bootstrap binaries and headers of the GNU C Library")
494 (description synopsis)
498 (define %bootstrap-gcc
499 ;; The initial GCC. Uses binaries from a tarball typically built by
500 ;; %GCC-BOOTSTRAP-TARBALL.
502 (name "gcc-bootstrap")
505 (build-system trivial-build-system)
507 `(#:guile ,%bootstrap-guile
508 #:modules ((guix build utils))
510 (let ((out (assoc-ref %outputs "out"))
511 (tar (assoc-ref %build-inputs "tar"))
512 (xz (assoc-ref %build-inputs "xz"))
513 (bash (assoc-ref %build-inputs "bash"))
514 (libc (assoc-ref %build-inputs "libc"))
515 (tarball (assoc-ref %build-inputs "tarball")))
516 (use-modules (guix build utils)
520 (copy-file tarball "binaries.tar.xz")
521 (invoke xz "-d" "binaries.tar.xz")
522 (let ((builddir (getcwd))
523 (bindir (string-append out "/bin")))
524 (with-directory-excursion out
526 (string-append builddir "/binaries.tar")))
528 (with-directory-excursion bindir
530 (rename-file "gcc" ".gcc-wrapped")
531 (call-with-output-file "gcc"
534 exec ~a/bin/.gcc-wrapped -B~a/lib \
535 -Wl,-rpath -Wl,~a/lib \
536 -Wl,-dynamic-linker -Wl,~a/~a \"$@\"~%"
539 ,(glibc-dynamic-linker))))
544 `(("tar" ,(search-bootstrap-binary "tar" (%current-system)))
545 ("xz" ,(search-bootstrap-binary "xz" (%current-system)))
546 ("bash" ,(search-bootstrap-binary "bash" (%current-system)))
547 ("libc" ,%bootstrap-glibc)
548 ("tarball" ,(bootstrap-origin
551 (uri (map (cut string-append <> "/" (%current-system)
552 (match (%current-system)
554 "/20150101/gcc-4.8.4.tar.xz")
556 "/20170217/gcc-5.4.0.tar.xz")
558 "/20131110/gcc-4.8.2.tar.xz")))
559 %bootstrap-base-urls))
561 (match (%current-system)
564 "17ga4m6195n4fnbzdkmik834znkhs53nkypp6557pl1ps7dgqbls"))
567 "150c1arrf2k8vfy6dpxh59vcgs4p1bgiz2av5m19dynpks7rjnyw"))
570 "0ghz825yzp43fxw53kd6afm8nkz16f7dxi9xi40bfwc8x3nbbr8v"))
573 "1ar3vdzyqbfm0z36kmvazvfswxhcihlacl2dzdjgiq25cqnq9ih1"))
576 "1m5miqkyng45l745n0sfafdpjkqv9225xf44jqkygwsipj2cv9ks")))))))))
578 (list (search-path-specification
580 (files '("include")))
581 (search-path-specification
582 (variable "LIBRARY_PATH")
583 (files '("lib" "lib64")))))
584 (synopsis "Bootstrap binaries of the GNU Compiler Collection")
585 (description synopsis)
589 (define %bootstrap-inputs
590 ;; The initial, pre-built inputs. From now on, we can start building our
592 `(("libc" ,%bootstrap-glibc)
593 ("gcc" ,%bootstrap-gcc)
594 ("binutils" ,%bootstrap-binutils)
595 ("coreutils&co" ,%bootstrap-coreutils&co)
597 ;; In gnu-build-system.scm, we rely on the availability of Bash.
598 ("bash" ,%bootstrap-coreutils&co)))
600 ;;; bootstrap.scm ends here