;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2014 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2012 Nikita Karetnikov <nikita@karetnikov.org>
;;; Copyright © 2014, 2015, 2017 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2017, 2018, 2019 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2019 Marius Bakke <mbakke@fastmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu packages commencement)
#:use-module ((guix licenses)
#:select (gpl3+ lgpl2.0+ public-domain))
#:use-module (gnu packages)
#:use-module (gnu packages bootstrap)
#:use-module (gnu packages base)
#:use-module (gnu packages bash)
#:use-module (gnu packages c)
#:use-module (gnu packages gcc)
#:use-module (gnu packages m4)
#:use-module (gnu packages file)
#:use-module (gnu packages gawk)
#:use-module (gnu packages bison)
#:use-module (gnu packages flex)
#:use-module (gnu packages guile)
#:use-module (gnu packages gettext)
#:use-module (gnu packages multiprecision)
#:use-module (gnu packages compression)
#:use-module (gnu packages mes)
#:use-module (gnu packages perl)
#:use-module (gnu packages python)
#:use-module (gnu packages linux)
#:use-module (gnu packages hurd)
#:use-module (gnu packages texinfo)
#:use-module (gnu packages pkg-config)
#:use-module (gnu packages xml)
#:use-module (guix packages)
#:use-module (guix download)
#:use-module (guix build-system gnu)
#:use-module (guix build-system trivial)
#:use-module (guix memoization)
#:use-module (guix utils)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (ice-9 vlist)
#:use-module (ice-9 match)
#:use-module (ice-9 regex)
#:export (make-gcc-toolchain))
;;; Commentary:
;;;
;;; This is the commencement, this is where things start. Before the
;;; commencement, of course, there's the 'bootstrap' module, which provides us
;;; with the initial binaries. This module uses those bootstrap binaries to
;;; actually build up the whole tool chain that make up the implicit inputs of
;;; 'gnu-build-system'.
;;;
;;; To avoid circular dependencies, this module should not be imported
;;; directly from anywhere.
;;;
;;; Below, we frequently use "inherit" to create modified packages. The
;;; reason why we use "inherit" instead of "package/inherit" is because we do
;;; not want these commencement packages to inherit grafts. By definition,
;;; these packages are not depended on at run time by any of the packages we
;;; use. Thus it does not make sense to inherit grafts. Furthermore, those
;;; grafts would often lead to extra overhead for users who would end up
;;; downloading those "-boot0" packages just to build package replacements
;;; that are in fact not going to be used.
;;;
;;; Code:
(define mes-boot
(package
(inherit mes)
(name "mes-boot")
(version "0.19")
(source (origin
(method url-fetch)
(uri (string-append "mirror://gnu/mes/"
"mes-" version ".tar.gz"))
(sha256
(base32
"15h4yhaywdc0djpjlin2jz1kzahpqxfki0r0aav1qm9nxxmnp1l0"))))
(inputs '())
(propagated-inputs '())
(native-inputs
`(("mescc-tools" ,%bootstrap-mescc-tools)
("nyacc-source" ,(bootstrap-origin
(package-source nyacc-0.86)))
("coreutils" , %bootstrap-coreutils&co)
("bootstrap-mes" ,%bootstrap-mes)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:strip-binaries? #f ; binutil's strip b0rkes MesCC/M1/hex2 binaries
#:phases
(modify-phases %standard-phases
(add-after 'unpack 'unpack-seeds
(lambda _
(let ((nyacc-source (assoc-ref %build-inputs "nyacc-source"))
(bootstrap-mes (assoc-ref %build-inputs "bootstrap-mes")))
(with-directory-excursion ".."
(mkdir-p "nyacc-source")
(invoke "tar" "--strip=1" "-C" "nyacc-source" "-xvf" nyacc-source)
(symlink (string-append bootstrap-mes "/share/mes/lib") "mes-seed"))
#t)))
(replace 'configure
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref %outputs "out")))
(setenv "GUILE" "mes")
(setenv "GUILE_EFFECTIVE_VERSION" "2.2")
(setenv "GUILE_LOAD_PATH" "nyacc")
(symlink (string-append "../nyacc-source/module") "nyacc")
(invoke "bash" "configure.sh"
(string-append "--prefix=" out)))))
(replace 'build
(lambda _
(let ((mes (assoc-ref %build-inputs "bootstrap-mes")))
(setenv "MES_PREFIX" (string-append mes "/share/mes"))
(setenv "MES_ARENA" "100000000")
(setenv "MES_MAX_ARENA" "100000000")
(setenv "MES_STACK" "10000000")
(invoke "sh" "bootstrap.sh"))))
(replace 'check
(lambda _
(setenv "DIFF" "sh scripts/diff.scm")
;; fail fast tests
;; (invoke "sh" "-x" "build-aux/test.sh" "scaffold/tests/t")
;; (invoke "sh" "-x" "build-aux/test.sh" "scaffold/tests/63-struct-cell")
(invoke "sh" "check.sh")))
(replace 'install
(lambda _
(invoke "sh" "install.sh"))))))
(native-search-paths
;; Use the language-specific variables rather than 'CPATH' because they
;; are equivalent to '-isystem' whereas 'CPATH' is equivalent to '-I'.
;; The intent is to allow headers that are in the search path to be
;; treated as "system headers" (headers exempt from warnings) just like
;; the typical /usr/include headers on an FHS system.
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("share/mes/include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("share/mes/lib")))))))
(define tcc-boot0
;; Pristine tcc cannot be built by MesCC, we are keeping a delta of 11
;; patches. In a very early and rough form they were presented to the
;; TinyCC developers, who at the time showed no interest in supporting the
;; bootstrappable effort; we will try again later. These patches have been
;; ported to 0.9.27, alas the resulting tcc is buggy. Once MesCC is more
;; mature, this package should use the 0.9.27 sources (or later).
(let ((version "0.9.26")
(revision "6")
(commit "c004e9a34fb026bb44d211ab98bb768e79900eef"))
(package
(inherit tcc)
(name "tcc-boot0")
(version (string-append version "-" revision "." (string-take commit 7)))
(source (origin
(method url-fetch)
(uri (string-append "https://gitlab.com/janneke/tinycc"
"/-/archive/" commit
"/tinycc-" commit ".tar.gz"))
(sha256
(base32
"1hmzn1pq0x22ppd80hyrn5qzqq94mxd0ychzj6vrr2vnj2frjv5b"))))
(build-system gnu-build-system)
(supported-systems '("i686-linux" "x86_64-linux"))
(inputs '())
(propagated-inputs '())
(native-inputs
`(("mes" ,mes-boot)
("mescc-tools" ,%bootstrap-mescc-tools)
("nyacc-source" ,(bootstrap-origin
(package-source nyacc-0.86)))
("coreutils" , %bootstrap-coreutils&co)
("bootstrap-mes" ,%bootstrap-mes)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:strip-binaries? #f ; binutil's strip b0rkes MesCC/M1/hex2 binaries
#:phases
(modify-phases %standard-phases
(add-after 'unpack 'unpack-seeds
(lambda* (#:key outputs #:allow-other-keys)
(let* ((coreutils (assoc-ref %build-inputs "coreutils"))
(nyacc-source (assoc-ref %build-inputs "nyacc-source"))
(bootstrap-mes (assoc-ref %build-inputs "bootstrap-mes")))
(setenv "PATH" (string-append
coreutils "/bin"))
(format (current-error-port) "PATH=~s\n" (getenv "PATH"))
(with-directory-excursion ".."
(mkdir-p "nyacc-source")
(invoke "tar" "--strip=1" "-C" "nyacc-source"
"-xvf" nyacc-source)
(symlink (string-append bootstrap-mes "/share/mes/lib") "mes-seed"))
#t)))
(replace 'configure
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref %outputs "out"))
(dir (with-directory-excursion ".." (getcwd)))
(coreutils (assoc-ref %build-inputs "coreutils"))
(mes (assoc-ref %build-inputs "mes"))
(mescc-tools (assoc-ref %build-inputs "mescc-tools"))
(libc (assoc-ref %build-inputs "libc"))
(interpreter (if libc
;; also for x86_64-linux, we are still on i686-linux
(string-append libc ,(glibc-dynamic-linker "i686-linux"))
(string-append mes "/lib/mes-loader"))))
(setenv "PATH" (string-append
coreutils "/bin"
":" mes "/bin"
":" mescc-tools "/bin"))
(format (current-error-port) "PATH=~s\n" (getenv "PATH"))
(setenv "PREFIX" out)
(symlink (string-append mes "/share/mes") "mes")
(symlink (string-append "../nyacc-source/module") "nyacc")
(setenv "MES_PREFIX" "mes")
(setenv "MES_ARENA" "100000000")
(setenv "MES_MAX_ARENA" "100000000")
(setenv "MES_STACK" "10000000")
(setenv "MES" "mes")
(setenv "GUILE_LOAD_PATH" "nyacc")
(invoke "sh" "configure"
"--prefix=$PREFIX"
(string-append "--elfinterp=" interpreter)
"--crtprefix=."
"--tccdir=."))))
(replace 'build
(lambda _
(substitute* "bootstrap.sh"
(("^ cmp") "# cmp"))
(invoke "sh" "bootstrap.sh")))
(replace 'check
(lambda _
(setenv "DIFF" "diff.scm")
(setenv "OBJDUMP" "true")
;; fail fast tests
;; (invoke "sh" "test.sh" "mes/scaffold/tests/30-strlen")
;; (invoke "sh" "-x" "test.sh" "mes/scaffold/tinycc/00_assignment")
(setenv "TCC" "./tcc")
(invoke "sh" "check.sh")))
(replace 'install
(lambda _
(invoke "sh" "install.sh"))))))
(native-search-paths
;; Use the language-specific variables rather than 'CPATH' because they
;; are equivalent to '-isystem' whereas 'CPATH' is equivalent to '-I'.
;; The intent is to allow headers that are in the search path to be
;; treated as "system headers" (headers exempt from warnings) just like
;; the typical /usr/include headers on an FHS system.
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib"))))))))
(define tcc-boot
(package
(inherit tcc-boot0)
(name "tcc-boot")
(version "0.9.27")
(source (bootstrap-origin
(origin
(inherit (package-source tcc))
(patches (search-patches "tcc-boot-0.9.27.patch")))))
(build-system gnu-build-system)
(inputs '())
(propagated-inputs '())
(native-inputs
`(("mes" ,mes-boot)
("tcc" ,tcc-boot0)
("coreutils" , %bootstrap-coreutils&co)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
;; Binutils' 'strip' b0rkes MesCC/M1/hex2 binaries, tcc-boot also comes
;; with MesCC/M1/hex2-built binaries.
#:strip-binaries? #f
#:phases
(modify-phases %standard-phases
(replace 'configure
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref %outputs "out"))
(coreutils (assoc-ref %build-inputs "coreutils"))
(mes (assoc-ref %build-inputs "mes"))
(tcc (assoc-ref %build-inputs "tcc"))
(libc (assoc-ref %build-inputs "libc"))
(interpreter (if libc
;; also for x86_64-linux, we are still on i686-linux
(string-append libc ,(glibc-dynamic-linker "i686-linux"))
(string-append mes "/lib/mes-loader"))))
;; unpack
(setenv "PATH" (string-append
coreutils "/bin"
":" tcc "/bin"))
(format (current-error-port) "PATH=~s\n" (getenv "PATH"))
(invoke "sh" "configure"
(string-append "--cc=tcc")
(string-append "--cpu=i386")
(string-append "--prefix=" out)
(string-append "--elfinterp=" interpreter)
(string-append "--crtprefix=" tcc "/lib")
(string-append "--sysincludepaths=" tcc "/include")
(string-append "--libpaths=" tcc "/lib")))))
(replace 'build
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref %outputs "out"))
(mes (assoc-ref %build-inputs "mes"))
(tcc (assoc-ref %build-inputs "tcc"))
(libc (assoc-ref %build-inputs "libc"))
(interpreter (if libc
;; also for x86_64-linux, we are still on i686-linux
(string-append libc ,(glibc-dynamic-linker "i686-linux"))
(string-append mes "/lib/mes-loader"))))
(invoke "tcc"
"-vvv"
"-D" "BOOTSTRAP=1"
"-D" "ONE_SOURCE=1"
"-D" "TCC_TARGET_I386=1"
"-D" "CONFIG_TCC_STATIC=1"
"-D" "CONFIG_USE_LIBGCC=1"
"-D" (string-append "CONFIG_TCCDIR=\"" out "/lib/tcc\"")
"-D" (string-append "CONFIG_TCC_CRTPREFIX=\"" out "/lib:{B}/lib:.\"")
"-D" (string-append "CONFIG_TCC_CRTPREFIX=\"" out
"/lib:{B}/lib:.\"")
"-D" (string-append "CONFIG_TCC_ELFINTERP=\"" interpreter "\"")
"-D" (string-append "CONFIG_TCC_LIBPATHS=\"" tcc "/lib:{B}/lib:.\"")
"-D" (string-append "CONFIG_TCC_SYSINCLUDEPATHS=\"" tcc "/include" ":/include:{B}/include\"")
"-D" (string-append "TCC_LIBGCC=\"" tcc "/lib/libc.a\"")
"-o" "tcc"
"tcc.c"))))
(replace 'check
(lambda _
;; FIXME: add sensible check target (without depending on make)
;; ./check.sh ?
(= 1 (status:exit-val (system* "./tcc" "--help")))))
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref %outputs "out"))
(tcc (assoc-ref %build-inputs "tcc")))
(mkdir-p (string-append out "/bin"))
(copy-file "tcc" (string-append out "/bin/tcc"))
(mkdir-p (string-append out "/lib/tcc"))
(copy-recursively (string-append tcc "/include")
(string-append out "/include"))
(copy-recursively (string-append tcc "/lib")
(string-append out "/lib"))
(invoke "tcc" "-D" "TCC_TARGET_I386=1" "-c" "-o" "libtcc1.o" "lib/libtcc1.c")
(invoke "tcc" "-ar" "rc" "libtcc1.a" "libtcc1.o")
(copy-file "libtcc1.a" (string-append out "/lib/libtcc1.a"))
(delete-file (string-append out "/lib/tcc/libtcc1.a"))
(copy-file "libtcc1.a" (string-append out "/lib/tcc/libtcc1.a"))
#t))))))))
(define make-mesboot0
(package
(inherit gnu-make)
(name "make-mesboot0")
(version "3.80")
(source (origin
(method url-fetch)
(uri (string-append "mirror://gnu/make/make-"
version ".tar.gz"))
(sha256
(base32
"1pb7fb7fqf9wz9najm85qdma1xhxzf1rhj5gwrlzdsz2zm0hpcv4"))))
(supported-systems '("i686-linux" "x86_64-linux"))
(inputs '())
(propagated-inputs '())
(native-inputs `(("tcc" ,tcc-boot)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)))
(arguments
`(#:implicit-inputs? #f
#:tests? #f ; check depends on perl
#:guile ,%bootstrap-guile
#:configure-flags `("CC=tcc -DO_RDONLY=0"
"LD=tcc"
"--disable-nls")
#:phases
(modify-phases %standard-phases
(add-after 'configure 'configure-fixup
(lambda _
(substitute* "build.sh"
(("^REMOTE=.*") "REMOTE=stub\n")
(("^extras=.*") "extras=getloadavg.c\n"))
(substitute* "make.h"
(("^extern long int lseek.*" all) (string-append "// " all)))
#t))
(delete 'patch-generated-file-shebangs) ; no perl
(replace 'build
(lambda _
(invoke "sh" "./build.sh")))
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(bin (string-append out "/bin")))
(install-file "make" bin)
#t))))))))
(define diffutils-mesboot
(package
(inherit diffutils)
(name "diffutils-mesboot")
(version "2.7")
(source (origin
(method url-fetch)
(uri (string-append "mirror://gnu/diffutils/diffutils-"
version ".tar.gz"))
(sha256
(base32
"1mirn5i825bn5w7rh6mgn0r8aj9xqanav95dwcl1b8sn82f4iwnm"))))
(supported-systems '("i686-linux" "x86_64-linux"))
(inputs '())
(propagated-inputs '())
(native-inputs `(("mes" ,mes-boot)
("tcc" ,tcc-boot)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("make" ,make-mesboot0)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:parallel-build? #f
#:tests? #f ; check is naive, also checks non-built PROGRAMS
#:strip-binaries? #f ; no strip yet
#:phases
(modify-phases %standard-phases
;; diffutils-2.7 needs more traditional configure
(replace 'configure
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out"))
(bash (assoc-ref %build-inputs "bash")))
(setenv "CONFIG_SHELL" (string-append bash "/bin/sh"))
(setenv "CC" "tcc")
(setenv "LD" "tcc")
(invoke "./configure" (string-append "--prefix=" out)))))
(add-before 'configure 'remove-diff3-sdiff
(lambda* (#:key outputs #:allow-other-keys)
(substitute* "Makefile.in"
(("PROGRAMS = .*" all) "PROGRAMS = cmp diff"))
#t)))))))
(define binutils-mesboot0
(package
(inherit binutils)
(name "binutils-mesboot0")
(version "2.20.1a")
(source (bootstrap-origin
(origin
(method url-fetch)
(uri (string-append "mirror://gnu/binutils/binutils-"
version ".tar.bz2"))
(patches (search-patches "binutils-boot-2.20.1a.patch"))
(sha256
(base32
"0r7dr0brfpchh5ic0z9r4yxqn4ybzmlh25sbp30cacqk8nb7rlvi")))))
(inputs '())
(propagated-inputs '())
(native-inputs `(("tcc" ,tcc-boot)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("make" ,make-mesboot0)))
(supported-systems '("i686-linux" "x86_64-linux"))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:tests? #f ; runtest: command not found
#:parallel-build? #f
#:strip-binaries? #f ; no strip yet
#:configure-flags
(let ((cppflags (string-append " -D __GLIBC_MINOR__=6"
" -D MES_BOOTSTRAP=1"))
(bash (assoc-ref %build-inputs "bash")))
`(,(string-append "CONFIG_SHELL=" bash "/bin/sh")
,(string-append "CPPFLAGS=" cppflags)
"AR=tcc -ar"
"CXX=false"
"RANLIB=true"
,(string-append "CC=tcc" cppflags)
"--disable-nls"
"--disable-shared"
"--disable-werror"
"--build=i686-unknown-linux-gnu"
"--host=i686-unknown-linux-gnu"
"--with-sysroot=/"))))))
(define gcc-core-mesboot
;; Gcc-2.95.3 is the most recent GCC that is supported by what the Mes C
;; Library v0.16 offers. Gcc-3.x (and 4.x) place higher demands on a C
;; library, such as dir.h/struct DIR/readdir, locales, signals... Also,
;; with gcc-2.95.3, binutils-boot-2.20.1a and glibc-2.2.5 we found a GNU
;; toolchain triplet "that works".
(package
(inherit gcc)
(name "gcc-core-mesboot")
(version "2.95.3")
(source (bootstrap-origin
(origin
(method url-fetch)
(uri (string-append "mirror://gnu/gcc/gcc-2.95.3/gcc-core-"
version
".tar.gz"))
(patches (search-patches "gcc-boot-2.95.3.patch"))
(sha256
(base32
"1xvfy4pqhrd5v2cv8lzf63iqg92k09g6z9n2ah6ndd4h17k1x0an")))))
(supported-systems '("i686-linux" "x86_64-linux"))
(inputs '())
(propagated-inputs '())
(native-inputs `(("binutils" ,binutils-mesboot0)
("tcc" ,tcc-boot)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("make" ,make-mesboot0)))
(outputs '("out"))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:tests? #f
#:parallel-build? #f
#:strip-binaries? #f
#:configure-flags
(let ((out (assoc-ref %outputs "out")))
`("--enable-static"
"--disable-shared"
"--disable-werror"
"--build=i686-unknown-linux-gnu"
"--host=i686-unknown-linux-gnu"
,(string-append "--prefix=" out)))
#:make-flags (list
"CC=tcc -static -D __GLIBC_MINOR__=6"
"OLDCC=tcc -static -D __GLIBC_MINOR__=6"
"CC_FOR_BUILD=tcc -static -D __GLIBC_MINOR__=6"
"AR=ar"
"RANLIB=ranlib"
(string-append "LIBGCC2_INCLUDES=-I "
(assoc-ref %build-inputs "tcc")
"/include")
"LANGUAGES=c"
(string-append "BOOT_LDFLAGS="
" -B" (assoc-ref %build-inputs "tcc")
"/lib/"))
#:modules ((guix build gnu-build-system)
(guix build utils)
(srfi srfi-1))
#:phases
(modify-phases %standard-phases
;; gcc-2.95.3 needs more traditional configure
(add-before 'configure 'setenv
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out"))
(bash (assoc-ref %build-inputs "bash"))
(tcc (assoc-ref %build-inputs "tcc"))
(cppflags " -D __GLIBC_MINOR__=6"))
(setenv "CONFIG_SHELL" (string-append bash "/bin/sh"))
(setenv "CPPFLAGS" cppflags)
(setenv "CC" (string-append "tcc" cppflags))
(setenv "CC_FOR_BUILD" (string-append "tcc" cppflags))
(setenv "CPP" (string-append "tcc -E" cppflags))
(with-output-to-file "config.cache"
(lambda _
(display "
ac_cv_c_float_format='IEEE (little-endian)'
")))
#t)))
(replace 'configure
(lambda* (#:key configure-flags #:allow-other-keys)
(format (current-error-port)
"running ./configure ~a\n" (string-join configure-flags))
(apply invoke "./configure" configure-flags)))
(add-after 'configure 'remove-info
(lambda _
;; no info at this stage
(delete-file-recursively "texinfo")
(invoke "touch" "gcc/cpp.info" "gcc/gcc.info")))
(add-after 'install 'install2
(lambda* (#:key outputs #:allow-other-keys)
(let* ((tcc (assoc-ref %build-inputs "tcc"))
(tcc-lib (string-append tcc "/lib/x86-mes-gcc"))
(out (assoc-ref outputs "out"))
(gcc-dir (string-append
out "/lib/gcc-lib/i686-unknown-linux-gnu/2.95.3")))
(mkdir-p "tmp")
(zero? (system (string-append "set -x; cd tmp && ar x ../gcc/libgcc2.a")))
(zero? (system (string-append "set -x; cd tmp && ar r " gcc-dir "/libgcc.a *.o")))
(copy-file "gcc/libgcc2.a" (string-append out "/lib/libgcc2.a"))
(copy-file (string-append tcc "/lib/libtcc1.a")
(string-append out "/lib/libtcc1.a"))
(invoke "ar" "r" (string-append gcc-dir "/libc.a")
(string-append tcc-lib "/libc+gnu.o")
(string-append tcc-lib "/libtcc1.o"))
(invoke "ar" "r" (string-append out "/lib/libc.a")
(string-append tcc-lib "/libc+gnu.o")
(string-append tcc-lib "/libtcc1.o"))
(invoke "ls" "-ltrF" gcc-dir)
(copy-recursively (string-append tcc "/include")
(string-append out "/include"))
#t))))))
(native-search-paths
;; Use the language-specific variables rather than 'CPATH' because they
;; are equivalent to '-isystem' whereas 'CPATH' is equivalent to '-I'.
;; The intent is to allow headers that are in the search path to be
;; treated as "system headers" (headers exempt from warnings) just like
;; the typical /usr/include headers on an FHS system.
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("include" "/lib/gcc-lib/i686-unknown-linux-gnu/2.95.3/include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib")))))))
(define mesboot-headers
(package
(inherit mes-boot)
(name "mesboot-headers")
(supported-systems '("i686-linux" "x86_64-linux"))
(inputs '())
(propagated-inputs '())
(native-inputs `(("coreutils" ,%bootstrap-coreutils&co)
("headers" ,%bootstrap-linux-libre-headers)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:tests? #f
#:strip-binaries? #f
#:phases
(modify-phases %standard-phases
(delete 'configure)
(delete 'build)
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(include (string-append out "/include"))
(headers (assoc-ref %build-inputs "headers" )))
(mkdir-p include)
(copy-recursively "include" out)
(copy-recursively headers out)
#t))))))
(native-search-paths
;; Use the language-specific variables rather than 'CPATH' because they
;; are equivalent to '-isystem' whereas 'CPATH' is equivalent to '-I'.
;; The intent is to allow headers that are in the search path to be
;; treated as "system headers" (headers exempt from warnings) just like
;; the typical /usr/include headers on an FHS system.
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("include")))))))
(define glibc-mesboot0
;; GNU C Library 2.2.5 is the most recent glibc that we managed to build
;; using gcc-2.95.3. Newer versions (2.3.x, 2.6, 2.1x) seem to need a newer
;; gcc.
(package
(inherit glibc)
(name "glibc-mesboot0")
(version "2.2.5")
(source (bootstrap-origin
(origin
(method url-fetch)
(uri (string-append "mirror://gnu/glibc/glibc-"
version
".tar.gz"))
(patches (search-patches "glibc-boot-2.2.5.patch"))
(sha256
(base32
"1vl48i16gx6h68whjyhgnn1s57vqq32f9ygfa2fls7pdkbsqvp2q")))))
(supported-systems '("i686-linux" "x86_64-linux"))
(inputs '())
(propagated-inputs '())
(native-inputs `(("binutils" ,binutils-mesboot0)
("gcc" ,gcc-core-mesboot)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("headers" ,mesboot-headers)
("make" ,make-mesboot0)))
(outputs '("out"))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:tests? #f
#:strip-binaries? #f
#:parallel-build? #f ; gcc-2.95.3 ICEs on massively parallel builds
#:make-flags (list (string-append
"SHELL="
(assoc-ref %build-inputs "bash")
"/bin/sh"))
#:configure-flags
(let ((out (assoc-ref %outputs "out"))
(headers (assoc-ref %build-inputs "headers")))
(list
"--disable-shared"
"--enable-static"
"--disable-sanity-checks"
"--build=i686-unknown-linux-gnu"
"--host=i686-unknown-linux-gnu"
(string-append "--with-headers=" headers "/include")
"--enable-static-nss"
"--without-__thread"
"--without-cvs"
"--without-gd"
"--without-tls"
(string-append "--prefix=" out)))
#:phases
(modify-phases %standard-phases
(add-before 'configure 'setenv
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(bash (assoc-ref %build-inputs "bash"))
(gcc (assoc-ref %build-inputs "gcc"))
(headers (assoc-ref %build-inputs "headers"))
(cppflags (string-append
;;" -D __STDC__=1"
" -D MES_BOOTSTRAP=1"
" -D BOOTSTRAP_GLIBC=1"))
(cflags (string-append " -L " (getcwd))))
(setenv "CONFIG_SHELL" (string-append bash "/bin/sh"))
(setenv "SHELL" (getenv "CONFIG_SHELL"))
(setenv "CPP" (string-append gcc "/bin/gcc -E " cppflags))
(setenv "CC" (string-append gcc "/bin/gcc " cppflags cflags))
#t)))
;; glibc-2.2.5 needs a more classic invocation of configure
;; configure: warning: CONFIG_SHELL=/gnu/store/…-bash-minimal-4.4.12/bin/bash: invalid host type
(replace 'configure
(lambda* (#:key configure-flags #:allow-other-keys)
(format (current-error-port)
"running ./configure ~a\n" (string-join configure-flags))
(apply invoke "./configure" configure-flags))))))
(native-search-paths
;; Use the language-specific variables rather than 'CPATH' because they
;; are equivalent to '-isystem' whereas 'CPATH' is equivalent to '-I'.
;; The intent is to allow headers that are in the search path to be
;; treated as "system headers" (headers exempt from warnings) just like
;; the typical /usr/include headers on an FHS system.
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("include")))
(search-path-specification
(variable "CPLUS_INCLUDE_PATH")
(files '("include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib")))))))
(define gcc-mesboot0
(package
(inherit gcc-core-mesboot)
(name "gcc-mesboot0")
(native-inputs `(("binutils" ,binutils-mesboot0)
("gcc" ,gcc-core-mesboot)
("libc" ,glibc-mesboot0)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("kernel-headers" ,%bootstrap-linux-libre-headers)
("make" ,make-mesboot0)))
(arguments
(substitute-keyword-arguments (package-arguments gcc-core-mesboot)
((#:phases phases)
`(modify-phases ,phases
(replace 'setenv
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out"))
(bash (assoc-ref %build-inputs "bash"))
(gcc (assoc-ref %build-inputs "gcc"))
(glibc (assoc-ref %build-inputs "libc"))
(kernel-headers (assoc-ref %build-inputs "kernel-headers")))
(setenv "CONFIG_SHELL" (string-append bash "/bin/sh"))
(format (current-error-port) "C_INCLUDE_PATH=~a\n" (getenv "C_INCLUDE_PATH"))
(setenv "C_INCLUDE_PATH" (string-append
gcc "/lib/gcc-lib/i686-unknown-linux-gnu/2.95.3/include"
":" kernel-headers "/include"
":" glibc "/include"))
(format (current-error-port) "C_INCLUDE_PATH=~a\n" (getenv "C_INCLUDE_PATH"))
(format (current-error-port) "LIBRARY_PATH=~a\n" (getenv "LIBRARY_PATH"))
;; FIXME: add glibc dirs to paths manually
(setenv "LIBRARY_PATH" (string-join
(list (string-append glibc "/lib")
(getenv "LIBRARY_PATH"))
":"))
(format (current-error-port) "LIBRARY_PATH=~a\n" (getenv "LIBRARY_PATH"))
(with-output-to-file "config.cache"
(lambda _
(display "
ac_cv_c_float_format='IEEE (little-endian)'
")))
#t)))
(replace 'install2
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(gcc-dir (string-append
out "/lib/gcc-lib/i686-unknown-linux-gnu/2.95.3")))
(mkdir-p "tmp")
(zero? (system (string-append "set -x; cd tmp && ar x ../gcc/libgcc2.a")))
(zero? (system (string-append "set -x; cd tmp && ar r " gcc-dir "/libgcc.a *.o")))
(copy-file "gcc/libgcc2.a" (string-append out "/lib/libgcc2.a"))
#t)))))
((#:configure-flags configure-flags)
`(let ((out (assoc-ref %outputs "out")))
`("--disable-shared"
"--disable-werror"
"--build=i686-unknown-linux-gnu"
"--host=i686-unknown-linux-gnu"
,(string-append "--prefix=" out))))
((#:make-flags make-flags)
`(let ((gcc (assoc-ref %build-inputs "gcc")))
`("RANLIB=true"
,(string-append "LIBGCC2_INCLUDES=-I " gcc "/include")
"LANGUAGES=c")))))))
(define binutils-mesboot
(package
(inherit binutils-mesboot0)
(name "binutils-mesboot")
(native-inputs `(("binutils" ,binutils-mesboot0)
("libc" ,glibc-mesboot0)
("gcc" ,gcc-mesboot0)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("kernel-headers" ,%bootstrap-linux-libre-headers)
("make" ,make-mesboot0)))
(arguments
(substitute-keyword-arguments (package-arguments binutils-mesboot0)
((#:configure-flags configure-flags)
'(list "--disable-nls"
"--disable-shared"
"--disable-werror"
"--build=i686-unknown-linux-gnu"
"--host=i686-unknown-linux-gnu"
"--with-sysroot=/"))))))
(define make-mesboot
(package
(inherit make-mesboot0)
(name "make-mesboot")
(version "3.82")
(source (origin
(method url-fetch)
(uri (string-append "mirror://gnu/make/make-"
version ".tar.gz"))
(sha256
(base32
"1rs2f9hmvy3q6zkl15jnlmnpgffm0bhw5ax0h5c7q604wqrip69x"))))
(native-inputs `(("binutils" ,binutils-mesboot0)
("libc" ,glibc-mesboot0)
("gcc" ,gcc-mesboot0)
("make" ,make-mesboot0)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("kernel-headers" ,%bootstrap-linux-libre-headers)))
(arguments
(substitute-keyword-arguments (package-arguments make-mesboot0)
((#:configure-flags configure-flags)
`(let ((out (assoc-ref %outputs "out")))
`(,(string-append "--prefix=" out))))
((#:phases phases)
`(modify-phases ,phases
(delete 'configure-fixup)
(add-before 'configure 'setenv
(lambda _
(setenv "LIBS" "-lc -lnss_files -lnss_dns -lresolv")
#t))))))))
(define gmp-boot
(package
(inherit gmp)
(version "4.3.2")
(source (origin
(method url-fetch)
(uri (string-append "mirror://gnu/gmp/gmp-" version
".tar.gz"))
(sha256 (base32
"15rwq54fi3s11izas6g985y9jklm3xprfsmym3v1g6xr84bavqvv"))))))
(define mpfr-boot
(package
(inherit mpfr)
(version "2.4.2")
(source (origin
(method url-fetch)
(uri (string-append "mirror://gnu/mpfr/mpfr-" version
".tar.gz"))
(sha256 (base32
"0dxn4904dra50xa22hi047lj8kkpr41d6vb9sd4grca880c7wv94"))))))
(define mpc-boot
(package
(inherit mpc)
(version "1.0.3")
(source (origin
(method url-fetch)
(uri (string-append
"mirror://gnu/mpc/mpc-" version ".tar.gz"))
(sha256
(base32
"1hzci2zrrd7v3g1jk35qindq05hbl0bhjcyyisq9z209xb3fqzb1"))))))
(define gcc-mesboot1
(package
(inherit gcc-mesboot0)
(name "gcc-mesboot1")
(version "4.7.4")
(source (bootstrap-origin
(origin (inherit (package-source gcc-4.7))
(patches (search-patches "gcc-boot-4.7.4.patch")))))
(inputs `(("gmp-source" ,(package-source gmp-boot))
("mpfr-source" ,(package-source mpfr-boot))
("mpc-source" ,(package-source mpc-boot))))
(native-inputs `(("binutils" ,binutils-mesboot)
("gcc" ,gcc-mesboot0)
("libc" ,glibc-mesboot0)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("kernel-headers" ,%bootstrap-linux-libre-headers)
("make" ,make-mesboot)))
(arguments
(substitute-keyword-arguments (package-arguments gcc-core-mesboot)
((#:make-flags make-flags)
`(let* ((libc (assoc-ref %build-inputs "libc"))
(ldflags (string-append
"-B" libc "/lib "
"-Wl,-dynamic-linker "
"-Wl," libc
,(glibc-dynamic-linker "i686-linux"))))
(list (string-append "LDFLAGS=" ldflags)
(string-append "LDFLAGS_FOR_TARGET=" ldflags))))
((#:phases phases)
`(modify-phases ,phases
;; c&p from commencement.scm:gcc-boot0
(add-after 'unpack 'unpack-gmp&co
(lambda* (#:key inputs #:allow-other-keys)
(let ((gmp (assoc-ref %build-inputs "gmp-source"))
(mpfr (assoc-ref %build-inputs "mpfr-source"))
(mpc (assoc-ref %build-inputs "mpc-source")))
;; To reduce the set of pre-built bootstrap inputs, build
;; GMP & co. from GCC.
(for-each (lambda (source)
(or (invoke "tar" "xvf" source)
(error "failed to unpack tarball"
source)))
(list gmp mpfr mpc))
;; Create symlinks like `gmp' -> `gmp-x.y.z'.
,@(map (lambda (lib)
;; Drop trailing letters, as gmp-6.0.0a unpacks
;; into gmp-6.0.0.
`(symlink ,(string-trim-right
(package-full-name lib "-")
char-set:letter)
,(package-name lib)))
(list gmp-boot mpfr-boot mpc-boot))
#t)))
(delete 'remove-info)
(replace 'setenv
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(binutils (assoc-ref %build-inputs "binutils"))
(bash (assoc-ref %build-inputs "bash"))
(gcc (assoc-ref %build-inputs "gcc"))
(glibc (assoc-ref %build-inputs "libc"))
(kernel-headers (assoc-ref %build-inputs "kernel-headers")))
(setenv "CONFIG_SHELL" (string-append bash "/bin/sh"))
(setenv "C_INCLUDE_PATH" (string-append
gcc "/lib/gcc-lib/i686-unknown-linux-gnu/2.95.3/include"
":" kernel-headers "/include"
":" glibc "/include"
":" (getcwd) "/mpfr/src"))
(setenv "LIBRARY_PATH" (string-append glibc "/lib"
":" gcc "/lib"))
(format (current-error-port) "C_INCLUDE_PATH=~a\n" (getenv "C_INCLUDE_PATH"))
(format (current-error-port) "LIBRARY_PATH=~a\n" (getenv "LIBRARY_PATH"))
#t)))
(delete 'install2)))
((#:configure-flags configure-flags)
`(let ((out (assoc-ref %outputs "out"))
(glibc (assoc-ref %build-inputs "libc")))
(list (string-append "--prefix=" out)
"--build=i686-unknown-linux-gnu"
"--host=i686-unknown-linux-gnu"
(string-append "--with-native-system-header-dir=" glibc "/include")
(string-append "--with-build-sysroot=" glibc "/include")
"--disable-bootstrap"
"--disable-decimal-float"
"--disable-libatomic"
"--disable-libcilkrts"
"--disable-libgomp"
"--disable-libitm"
"--disable-libmudflap"
"--disable-libquadmath"
"--disable-libsanitizer"
"--disable-libssp"
"--disable-libvtv"
"--disable-lto"
"--disable-lto-plugin"
"--disable-multilib"
"--disable-plugin"
"--disable-threads"
"--enable-languages=c,c++"
"--enable-static"
;; libstdc++.so: error: depends on 'libgcc_s.so.1', which cannot be found in RUNPATH ()
"--disable-shared"
"--enable-threads=single"
;; No pre-compiled libstdc++ headers, to save space.
"--disable-libstdcxx-pch"
;; for libcpp ...
"--disable-build-with-cxx")))))))
(define gcc-mesboot1-wrapper
;; We need this so gcc-mesboot1 can be used to create shared binaries that
;; have the correct interpreter, otherwise configuring gcc-mesboot using
;; --enable-shared will fail.
(package
(inherit gcc-mesboot1)
(name "gcc-mesboot1-wrapper")
(source #f)
(inputs '())
(native-inputs `(("bash" ,%bootstrap-coreutils&co)
("libc" ,glibc-mesboot)
("gcc" ,gcc-mesboot1)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:phases
(modify-phases %standard-phases
(delete 'unpack)
(delete 'configure)
(delete 'install)
(replace 'build
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(bash (assoc-ref %build-inputs "bash"))
(libc (assoc-ref %build-inputs "libc"))
(gcc (assoc-ref %build-inputs "gcc"))
(bin (string-append out "/bin")))
(mkdir-p bin)
(for-each
(lambda (program)
(let ((wrapper (string-append bin "/" program)))
(with-output-to-file wrapper
(lambda _
(display (string-append "#! " bash "/bin/bash
exec " gcc "/bin/" program
" -Wl,--dynamic-linker"
;; also for x86_64-linux, we are still on i686-linux
" -Wl," libc ,(glibc-dynamic-linker "i686-linux")
" -Wl,--rpath"
" -Wl," libc "/lib"
" \"$@\"
"))
(chmod wrapper #o555)))))
'(
"gcc"
"g++"
"i686-unknown-linux-gnu-gcc"
"i686-unknown-linux-gnu-g++"
))
#t)))
(replace 'check
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(bin (string-append out "/bin"))
(program (string-append bin "/gcc")))
(invoke program "--help")))))))))
(define glibc-headers-mesboot
(package
(inherit glibc-mesboot0)
(name "glibc-headers-mesboot")
(version "2.16.0")
(source (bootstrap-origin
(origin
(method url-fetch)
(uri (string-append "mirror://gnu/glibc/glibc-"
version
".tar.gz"))
(patches (search-patches "glibc-boot-2.16.0.patch"
"glibc-bootstrap-system-2.16.0.patch"))
(sha256
(base32
"0vlz4x6cgz7h54qq4528q526qlhnsjzbsvgc4iizn76cb0bfanx7")))))
(native-inputs `(("binutils" ,binutils-mesboot)
("libc" ,glibc-mesboot0)
("gcc" ,gcc-mesboot1)
("headers" ,mesboot-headers)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("kernel-headers" ,%bootstrap-linux-libre-headers)
("make" ,make-mesboot)))
(arguments
(substitute-keyword-arguments (package-arguments glibc-mesboot0)
((#:configure-flags configure-flags)
`(let ((out (assoc-ref %outputs "out"))
(headers (assoc-ref %build-inputs "headers")))
(list
(string-append "--prefix=" out)
"--disable-obsolete-rpc"
"--host=i686-unknown-linux-gnu"
(string-append "--with-headers=" headers "/include")
"--enable-static-nss"
"--with-pthread"
"--without-cvs"
"--without-gd"
"--enable-add-ons=nptl")))
((#:make-flags make-flags)
`(let ((bash (assoc-ref %build-inputs "bash")))
(list (string-append "SHELL=" bash "/bin/sh")
"install-bootstrap-headers=yes" "install-headers")))
((#:phases phases)
`(modify-phases ,phases
(replace 'setenv
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(headers (assoc-ref %build-inputs "headers"))
(bash (assoc-ref %build-inputs "bash"))
(coreutils (assoc-ref %build-inputs "coreutils"))
(libc (assoc-ref %build-inputs "libc"))
(gcc (assoc-ref %build-inputs "gcc"))
(cppflags (string-append
" -I " (getcwd) "/nptl/sysdeps/pthread/bits"
" -D BOOTSTRAP_GLIBC=1"))
(cflags (string-append " -L " (getcwd)
" -L " libc "/lib")))
(setenv "libc_cv_friendly_stddef" "yes")
(setenv "CONFIG_SHELL" (string-append bash "/bin/sh"))
(setenv "SHELL" (getenv "CONFIG_SHELL"))
(format (current-error-port) "CONFIG_SHELL=~s\n" (getenv "CONFIG_SHELL"))
(setenv "CPP" (string-append gcc "/bin/gcc -E " cppflags))
(setenv "CC" (string-append gcc "/bin/gcc " cppflags cflags))
;; avoid -fstack-protector
(setenv "libc_cv_ssp" "false")
(substitute* "configure"
(("/bin/pwd") (string-append coreutils "/bin/pwd")))
(setenv "C_INCLUDE_PATH" (string-append libc "/include"
headers "/include"))
(setenv "LIBRARY_PATH" (string-append libc "/lib"))
#t)))
(replace 'install
(lambda* (#:key outputs make-flags #:allow-other-keys)
(let ((kernel-headers (assoc-ref %build-inputs "kernel-headers"))
(out (assoc-ref outputs "out")))
(apply invoke "make" make-flags)
(copy-recursively kernel-headers out)
#t)))
(replace 'configure
(lambda* (#:key configure-flags #:allow-other-keys)
(format (current-error-port) "running ../configure ~a\n" (string-join configure-flags))
(mkdir-p "build")
(chdir "build")
(apply invoke "../configure" configure-flags)))
(add-after 'configure 'remove-sunrpc
(lambda _
(invoke "make" (string-append (getcwd) "/sysd-sorted" )
(string-append "SHELL=" (getenv "CONFIG_SHELL")))
(substitute* "sysd-sorted"
((" sunrpc") " ")
((" nis") " "))
;; 'rpcgen' needs native libc headers to be built.
(substitute* "../Makefile"
(("^SHELL := /bin/sh") (string-append "SHELL := " (getenv "CONFIG_SHELL"))))
(substitute* "../Makeconfig"
(("^SHELL := /bin/sh") (string-append "SHELL := " (getenv "CONFIG_SHELL"))))
(substitute* "../elf/Makefile"
(("^SHELL := /bin/sh") (string-append "SHELL := " (getenv "CONFIG_SHELL"))))))))))))
(define glibc-mesboot
(package
(inherit glibc-headers-mesboot)
(name "glibc-mesboot")
(native-inputs `(("binutils" ,binutils-mesboot)
("libc" ,glibc-mesboot0)
("headers" ,glibc-headers-mesboot)
("gcc" ,gcc-mesboot1)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("kernel-headers" ,%bootstrap-linux-libre-headers)
("make" ,make-mesboot)))
(arguments
`(#:validate-runpath? #f ; fails when using --enable-shared
,@(substitute-keyword-arguments (package-arguments glibc-headers-mesboot)
((#:make-flags make-flags)
`(let ((bash (assoc-ref %build-inputs "bash")))
(list (string-append "SHELL=" bash "/bin/sh"))))
((#:phases phases)
`(modify-phases ,phases
(replace 'install
(lambda* (#:key outputs make-flags #:allow-other-keys)
(let* ((kernel-headers (assoc-ref %build-inputs "kernel-headers"))
(out (assoc-ref outputs "out"))
(install-flags (cons "install" make-flags)))
(apply invoke "make" install-flags)
(copy-recursively kernel-headers out)
#t))))))))
(native-search-paths ;; FIXME: move to glibc-mesboot0
;; Use the language-specific variables rather than 'CPATH' because they
;; are equivalent to '-isystem' whereas 'CPATH' is equivalent to '-I'.
;; The intent is to allow headers that are in the search path to be
;; treated as "system headers" (headers exempt from warnings) just like
;; the typical /usr/include headers on an FHS system.
(list (search-path-specification
(variable "C_INCLUDE_PATH")
(files '("include")))
(search-path-specification
(variable "CPLUS_INCLUDE_PATH")
(files '("include")))
(search-path-specification
(variable "LIBRARY_PATH")
(files '("lib")))))))
(define gcc-mesboot
(package
(inherit gcc-mesboot1)
(name "gcc-mesboot")
(version "4.9.4")
(source (bootstrap-origin (package-source gcc-4.9)))
(native-inputs `(("binutils" ,binutils-mesboot)
("gcc-wrapper" ,gcc-mesboot1-wrapper)
("gcc" ,gcc-mesboot1)
("libc" ,glibc-mesboot)
("bash" ,%bootstrap-coreutils&co)
("coreutils" ,%bootstrap-coreutils&co)
("diffutils" ,diffutils-mesboot)
("kernel-headers" ,%bootstrap-linux-libre-headers)
("make" ,make-mesboot)))
(arguments
`(#:validate-runpath? #f
,@(substitute-keyword-arguments (package-arguments gcc-mesboot1)
((#:configure-flags configure-flags)
`(let ((out (assoc-ref %outputs "out"))
(glibc (assoc-ref %build-inputs "libc")))
(list (string-append "--prefix=" out)
"--build=i686-unknown-linux-gnu"
"--host=i686-unknown-linux-gnu"
"--with-host-libstdcxx=-lsupc++"
(string-append "--with-native-system-header-dir=" glibc "/include")
(string-append "--with-build-sysroot=" glibc "/include")
"--disable-bootstrap"
"--disable-decimal-float"
"--disable-libatomic"
"--disable-libcilkrts"
"--disable-libgomp"
"--disable-libitm"
"--disable-libmudflap"
"--disable-libquadmath"
"--disable-libsanitizer"
"--disable-libssp"
"--disable-libvtv"
"--disable-lto"
"--disable-lto-plugin"
"--disable-multilib"
"--disable-plugin"
"--disable-threads"
"--enable-languages=c,c++"
"--enable-static"
"--enable-shared"
"--enable-threads=single"
;; No pre-compiled libstdc++ headers, to save space.
"--disable-libstdcxx-pch"
;; for libcpp ...
"--disable-build-with-cxx")))
((#:phases phases)
`(modify-phases ,phases
(replace 'setenv
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(binutils (assoc-ref %build-inputs "binutils"))
(bash (assoc-ref %build-inputs "bash"))
(gcc (assoc-ref %build-inputs "gcc"))
(glibc (assoc-ref %build-inputs "libc"))
(kernel-headers (assoc-ref %build-inputs "kernel-headers")))
(setenv "CONFIG_SHELL" (string-append bash "/bin/sh"))
(setenv "C_INCLUDE_PATH" (string-append
gcc "/lib/gcc-lib/i686-unknown-linux-gnu/4.7.4/include"
":" kernel-headers "/include"
":" glibc "/include"
":" (getcwd) "/mpfr/src"))
(setenv "CPLUS_INCLUDE_PATH" (string-append
gcc "/lib/gcc-lib/i686-unknown-linux-gnu/4.7.4/include"
":" kernel-headers "/include"
":" glibc "/include"
":" (getcwd) "/mpfr/src"))
(setenv "LIBRARY_PATH" (string-append glibc "/lib"
":" gcc "/lib"))
(format (current-error-port) "C_INCLUDE_PATH=~a\n" (getenv "C_INCLUDE_PATH"))
(format (current-error-port) "CPLUS_INCLUDE_PATH=~a\n" (getenv "CPLUS_INCLUDE_PATH"))
(format (current-error-port) "LIBRARY_PATH=~a\n" (getenv "LIBRARY_PATH"))
#t))))))))))
(define gcc-mesboot-wrapper
;; We need this so gcc-mesboot can be used to create shared binaries that
;; have the correct interpreter and runpath to libc.
(package
(inherit gcc-mesboot1-wrapper)
(name "gcc-mesboot-wrapper")
(version (package-version gcc-mesboot))
(source #f)
(inputs '())
(native-inputs `(("bash" ,%bootstrap-coreutils&co)
("libc" ,glibc-mesboot)
("gcc" ,gcc-mesboot)))))
(define m4-mesboot
(package
(inherit m4)
(name "m4-mesboot")
(version "1.4")
(source (origin
(method url-fetch)
(uri (string-append "mirror://gnu/m4/m4-"
version ".tar.gz"))
(sha256
(base32
"1f9bxj176kf3pvs350w2dfs8jgwhminywri5pyn01b11yc4yhsjw"))))
(supported-systems '("i686-linux" "x86_64-linux"))
(native-inputs `(("mes" ,mes-boot)
("tcc" ,tcc-boot)))
(arguments
`(#:phases
(modify-phases %standard-phases
(replace 'configure
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out")))
(setenv "CONFIG_SHELL" (string-append
(assoc-ref %build-inputs "bash")
"/bin/sh"))
(setenv "CC" "tcc -static")
(setenv "CPP" "tcc -E")
(invoke "./configure" (string-append "--prefix=" out))))))))))
(define (%bootstrap-inputs+toolchain)
;; The traditional bootstrap-inputs. For the i686-linux Reduced Binary Seed
;; the actual reduced set with bootstrapped toolchain.
(match (%current-system)
((or "i686-linux" "x86_64-linux")
`(("libc" ,glibc-mesboot)
("binutils" ,binutils-mesboot)
("gcc-wrapper" ,gcc-mesboot-wrapper)
("gcc" ,gcc-mesboot)
,@(fold alist-delete (%bootstrap-inputs)
'("bootstrap-mescc-tools" "mes"))))
(_
(%bootstrap-inputs))))
(define gnu-make-boot0
(package
(inherit gnu-make)
(source (bootstrap-origin (package-source gnu-make)))
(name "make-boot0")
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
#:tests? #f ; cannot run "make check"
,@(substitute-keyword-arguments (package-arguments gnu-make)
((#:phases phases)
`(modify-phases ,phases
(replace 'build
(lambda _
(invoke "./build.sh")))
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
(let* ((out (assoc-ref outputs "out"))
(bin (string-append out "/bin")))
(install-file "make" bin)
#t))))))))
(native-inputs '()) ; no need for 'pkg-config'
(inputs (%bootstrap-inputs+toolchain))))
(define diffutils-boot0
(package
(inherit diffutils)
(name "diffutils-boot0")
(native-inputs `())
(inputs
`(("make" ,gnu-make-boot0)
,@(%bootstrap-inputs+toolchain)))
(arguments
`(#:tests? #f ; the test suite needs diffutils
#:guile ,%bootstrap-guile
#:implicit-inputs? #f
,@(package-arguments diffutils)))))
(define findutils-boot0
(package
(inherit findutils)
(name "findutils-boot0")
(source (bootstrap-origin (package-source findutils)))
(inputs
`(("make" ,gnu-make-boot0)
("diffutils" ,diffutils-boot0) ; for tests
,@(%bootstrap-inputs+toolchain)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
,@(package-arguments findutils)))))
(define file-boot0
(package
(inherit file)
(source (bootstrap-origin (package-source file)))
(name "file-boot0")
(inputs
`(("make" ,gnu-make-boot0)
,@(%bootstrap-inputs+toolchain)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:strip-binaries? #f
#:validate-runpath? #f))))
(define (%boot0-inputs)
`(("make" ,gnu-make-boot0)
("diffutils" ,diffutils-boot0)
("findutils" ,findutils-boot0)
("file" ,file-boot0)
,@(%bootstrap-inputs+toolchain)))
(define* (boot-triplet #:optional (system (%current-system)))
;; Return the triplet used to create the cross toolchain needed in the
;; first bootstrapping stage.
(nix-system->gnu-triplet system "guix"))
;; Following Linux From Scratch, build a cross-toolchain in stage 0. That
;; toolchain actually targets the same OS and arch, but it has the advantage
;; of being independent of the libc and tools in
;; (%BOOTSTRAP-INPUTS+TOOLCHAIN), since GCC-BOOT0 (below) is built without any
;; reference to the target libc.
(define binutils-boot0
(package
(inherit binutils)
(source (bootstrap-origin (package-source binutils)))
(name "binutils-cross-boot0")
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
#:modules ((guix build gnu-build-system)
(guix build utils)
(ice-9 ftw)) ; for 'scandir'
#:phases (modify-phases %standard-phases
(add-after 'install 'add-symlinks
(lambda* (#:key outputs #:allow-other-keys)
;; The cross-gcc invokes 'as', 'ld', etc, without the
;; triplet prefix, so add symlinks.
(let ((out (assoc-ref outputs "out"))
(triplet-prefix (string-append ,(boot-triplet) "-")))
(define (has-triplet-prefix? name)
(string-prefix? triplet-prefix name))
(define (remove-triplet-prefix name)
(substring name (string-length triplet-prefix)))
(with-directory-excursion (string-append out "/bin")
(for-each (lambda (name)
(symlink name (remove-triplet-prefix name)))
(scandir "." has-triplet-prefix?)))
#t))))
,@(substitute-keyword-arguments (package-arguments binutils)
((#:configure-flags cf)
`(cons ,(string-append "--target=" (boot-triplet))
,cf)))))
(inputs (%boot0-inputs))))
(define libstdc++-boot0
;; GCC's libcc1 is always built as a shared library (the top-level
;; 'Makefile.def' forcefully adds --enable-shared) and thus needs to refer
;; to libstdc++.so. We cannot build libstdc++-5.3 because it relies on
;; C++14 features missing in some of our bootstrap compilers.
(let ((lib (make-libstdc++ gcc-4.9)))
(package
(inherit lib)
(source (bootstrap-origin (package-source lib)))
(name "libstdc++-boot0")
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
;; XXX: libstdc++.so NEEDs ld.so for some reason.
#:validate-runpath? #f
,@(match (%current-system)
((or "i686-linux" "x86_64-linux")
(substitute-keyword-arguments (package-arguments lib)
((#:phases phases)
`(modify-phases ,phases
(add-after 'unpack 'workaround-wrapper-bug
;; XXX: The crude gcc-cross-wrapper causes "g++ -v" to
;; fail, which in turn confuses the configure script.
(lambda _
(substitute* "libstdc++-v3/configure"
(("g\\+\\+ -v") "true"))
#t))))))
(_ (package-arguments lib)))))
(inputs (%boot0-inputs))
(native-inputs '()))))
(define gcc-boot0
(package
(inherit gcc)
(name "gcc-cross-boot0")
(source (bootstrap-origin (package-source gcc)))
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
#:modules ((guix build gnu-build-system)
(guix build utils)
(ice-9 regex)
(srfi srfi-1)
(srfi srfi-26))
,@(substitute-keyword-arguments (package-arguments gcc)
((#:configure-flags flags)
`(append (list ,(string-append "--target=" (boot-triplet))
;; No libc yet.
"--without-headers"
;; Disable features not needed at this stage.
"--disable-shared"
"--enable-languages=c,c++"
;; libstdc++ cannot be built at this stage
;; ("Link tests are not allowed after
;; GCC_NO_EXECUTABLES.").
"--disable-libstdc++-v3"
"--disable-threads"
"--disable-libmudflap"
"--disable-libatomic"
"--disable-libsanitizer"
"--disable-libitm"
"--disable-libgomp"
"--disable-libmpx"
"--disable-libcilkrts"
"--disable-libvtv"
"--disable-libssp"
"--disable-libquadmath"
"--disable-decimal-float")
(remove (cut string-match
"--(with-system-zlib|enable-languages.*)" <>)
,flags)))
((#:make-flags flags)
`(let* ((libc (assoc-ref %build-inputs "libc"))
(libc-native (or (assoc-ref %build-inputs "libc-native")
libc)))
`(,(string-append "LDFLAGS="
"-Wl,-rpath=" libc-native "/lib "
"-Wl,-dynamic-linker "
"-Wl," libc-native ,(glibc-dynamic-linker
(match (%current-system)
("x86_64-linux" "i686-linux")
(_ (%current-system))))))))
((#:phases phases)
`(modify-phases ,phases
(add-after 'unpack 'unpack-gmp&co
(lambda* (#:key inputs #:allow-other-keys)
(let ((gmp (assoc-ref %build-inputs "gmp-source"))
(mpfr (assoc-ref %build-inputs "mpfr-source"))
(mpc (assoc-ref %build-inputs "mpc-source")))
;; To reduce the set of pre-built bootstrap inputs, build
;; GMP & co. from GCC.
(for-each (lambda (source)
(invoke "tar" "xvf" source))
(list gmp mpfr mpc))
;; Create symlinks like `gmp' -> `gmp-x.y.z'.
,@(map (lambda (lib)
;; Drop trailing letters, as gmp-6.0.0a unpacks
;; into gmp-6.0.0.
`(symlink ,(string-trim-right
(package-full-name lib "-")
char-set:letter)
,(package-name lib)))
(list gmp-6.0 mpfr mpc))
#t)))
,(match (%current-system)
((or "i686-linux" "x86_64-linux")
'(add-before 'configure 'fix-libcc1
(lambda* (#:key inputs #:allow-other-keys)
;; libcc1.so NEEDs libgcc_s.so, so provide one here
;; to placate the 'validate-runpath' phase.
(substitute* "libcc1/Makefile.in"
(("la_LDFLAGS =")
(string-append "la_LDFLAGS = -Wl,-rpath="
(assoc-ref inputs "gcc") "/lib")))
;; XXX: "g++ -v" is broken (see also libstdc++ above).
(substitute* "libcc1/configure"
(("g\\+\\+ -v") "true"))
#t)))
(_ '(add-before 'configure 'return-true
(lambda _ #t))))
(add-after 'install 'symlink-libgcc_eh
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "lib")))
;; Glibc wants to link against libgcc_eh, so provide
;; it.
(with-directory-excursion
(string-append out "/lib/gcc/"
,(boot-triplet)
"/" ,(package-version gcc))
(symlink "libgcc.a" "libgcc_eh.a"))
#t))))))))
(inputs `(("gmp-source" ,(bootstrap-origin (package-source gmp-6.0)))
("mpfr-source" ,(bootstrap-origin (package-source mpfr)))
("mpc-source" ,(bootstrap-origin (package-source mpc)))
("binutils-cross" ,binutils-boot0)
;; The libstdc++ that libcc1 links against.
("libstdc++" ,libstdc++-boot0)
;; Call it differently so that the builder can check whether
;; the "libc" input is #f.
("libc-native" ,@(assoc-ref (%boot0-inputs) "libc"))
,@(alist-delete "libc" (%boot0-inputs))))
;; No need for the native-inputs to build the documentation at this stage.
(native-inputs `())))
(define perl-boot0
(package
(inherit perl)
(name "perl-boot0")
(source (bootstrap-origin (package-source perl)))
(inputs (%boot0-inputs))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:validate-runpath? #f
;; At the very least, this must not depend on GCC & co.
#:disallowed-references ,(list %bootstrap-binutils)
,@(substitute-keyword-arguments (package-arguments perl)
((#:phases phases)
`(modify-phases ,phases
;; Pthread support is missing in the bootstrap compiler
;; (broken spec file), so disable it.
(add-before 'configure 'disable-pthreads
(lambda _
(substitute* "Configure"
(("^libswanted=(.*)pthread" _ before)
(string-append "libswanted=" before)))
#t))))
;; Do not configure with '-Dusethreads' since pthread
;; support is missing.
((#:configure-flags configure-flags)
`(delete "-Dusethreads" ,configure-flags)))))))
(define m4-boot0
(package
(inherit m4)
(name "m4-boot0")
(source (bootstrap-origin (package-source m4)))
(inputs (%boot0-inputs))
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
,@(package-arguments m4)))))
(define m4-boot0*
(package
;; TODO: On the next rebuild cycle, use M4-BOOT0 as is.
(inherit m4-boot0)
(name "m4")))
(define bison-boot0
;; This Bison is needed to build MiG so we need it early in the process.
;; Recent versions of Linux-Libre headers also depend on this.
(package
(inherit bison)
;; TODO: On the next build cycle, do:
;;(name "bison-boot0")
(propagated-inputs `(("m4" ,m4-boot0*)))
(native-inputs `(("perl" ,perl-boot0)))
(inputs (%boot0-inputs)) ;remove Flex...
(arguments
`(#:tests? #f ;... and thus disable tests
#:implicit-inputs? #f
#:guile ,%bootstrap-guile
;; XXX: These flags should be unconditional, but for now
;; we just add them on x86 to avoid a full rebuild.
;; TODO: On the next core-updates, use
;; 'substitute-keyword-arguments' to inherit them from
;; BISON.
,@(if (member (%current-system)
'("x86_64-linux" "i686-linux"))
'(#:parallel-build? #f
#:parallel-tests? #f)
'())
;; Zero timestamps in liby.a; this must be done
;; explicitly here because the bootstrap Binutils don't
;; do that (default is "cru".)
#:make-flags `("ARFLAGS=crD"
,,(match (%current-system)
;; ranlib: '-D': No such file
((or "i686-linux" "x86_64-linux")
"RANLIB=ranlib")
(_
"RANLIB=ranlib -D"))
"V=1")))))
(define flex-boot0
;; This Flex is needed to build MiG as well as Linux-Libre headers.
(package
(inherit flex)
(native-inputs `(("bison" ,bison-boot0)))
(propagated-inputs
;; XXX: Here we use an 'm4-boot0' package that's not eq? so that it
;; appears twice in '%build-inputs', like when we were using
;; 'package-with-explicit-inputs'.
;; TODO: Remove this hack on the next rebuild cycle.
`(("m4" ,(package (inherit m4-boot0*)))))
(inputs (%boot0-inputs))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:tests? #f))))
(define linux-libre-headers-boot0
(mlambda ()
"Return Linux-Libre header files for the bootstrap environment."
;; Note: this is wrapped in a thunk to nicely handle circular dependencies
;; between (gnu packages linux) and this module. Additionally, memoize
;; the result to play well with further memoization and code that relies
;; on pointer identity; see <https://bugs.gnu.org/30155>.
(package
(inherit linux-libre-headers)
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
,@(package-arguments linux-libre-headers)))
(native-inputs
`(("perl" ,perl-boot0)
;; Flex and Bison are required since version 4.16.
("flex" ,flex-boot0)
("bison" ,bison-boot0)
,@(%boot0-inputs))))))
(define with-boot0
(package-with-explicit-inputs %boot0-inputs
%bootstrap-guile))
(define gnumach-headers-boot0
(with-boot0 (package-with-bootstrap-guile gnumach-headers)))
(define mig-boot0
(let* ((mig (package
(inherit (package-with-bootstrap-guile mig))
(native-inputs `(("bison" ,bison-boot0)
("flex" ,flex-boot0)))
(inputs `(("flex" ,flex-boot0)))
(arguments
`(#:configure-flags
`(,(string-append "LDFLAGS=-Wl,-rpath="
(assoc-ref %build-inputs "flex") "/lib/")))))))
(with-boot0 mig)))
(define hurd-headers-boot0
(let ((hurd-headers (package (inherit hurd-headers)
(native-inputs `(("mig" ,mig-boot0)))
(inputs '()))))
(with-boot0 (package-with-bootstrap-guile hurd-headers))))
(define hurd-minimal-boot0
(let ((hurd-minimal (package (inherit hurd-minimal)
(native-inputs `(("mig" ,mig-boot0)))
(inputs '()))))
(with-boot0 (package-with-bootstrap-guile hurd-minimal))))
(define hurd-core-headers-boot0
(mlambda ()
"Return the Hurd and Mach headers as well as initial Hurd libraries for
the bootstrap environment."
(package (inherit (package-with-bootstrap-guile hurd-core-headers))
(arguments `(#:guile ,%bootstrap-guile
,@(package-arguments hurd-core-headers)))
(inputs
`(("gnumach-headers" ,gnumach-headers-boot0)
("hurd-headers" ,hurd-headers-boot0)
("hurd-minimal" ,hurd-minimal-boot0)
,@(%boot0-inputs))))))
(define* (kernel-headers-boot0 #:optional (system (%current-system)))
(match system
("i586-gnu" (hurd-core-headers-boot0))
(_ (linux-libre-headers-boot0))))
(define texinfo-boot0
;; Texinfo used to build libc's manual.
;; We build without ncurses because it fails to build at this stage, and
;; because we don't need the stand-alone Info reader.
;; Also, use (%BOOT0-INPUTS) to avoid building Perl once more.
(package
(inherit texinfo)
(native-inputs '())
(inputs `(,@(%boot0-inputs)
("perl" ,perl-boot0)))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
;; Some of Texinfo 6.1's tests would fail with "Couldn't set UTF-8
;; character type in locale" but we don't have a UTF-8 locale at this
;; stage, so skip them.
#:tests? #f))))
(define expat-sans-tests
(package
(inherit expat)
(inputs (%boot0-inputs))
(arguments
;; XXX: Linking 'runtestscpp' fails with things like:
;;
;; ld: Dwarf Error: found dwarf version '3789', this reader only handles version 2 and 3 information.
;;
;; Skip tests altogether.
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
,@(substitute-keyword-arguments (package-arguments expat)
((#:configure-flags flags ''())
;; Since we're not passing the right -Wl,-rpath flags, build the
;; static library to avoid RUNPATH validation failure.
`(cons "--disable-shared" ,flags))
((#:tests? _ #f) #f))))))
(define python-boot0
(package
(inherit python-minimal)
;; We cannot use Python 3.7 and later here, because they require
;; pthreads, which is missing on non-x86 platforms at this stage.
;; Python 3.6 technically supports being built without threading
;; support, but requires additional patches.
(version "3.5.7")
(source (bootstrap-origin
(origin
(inherit (package-source python))
(uri (string-append "https://www.python.org/ftp/python/"
version "/Python-" version ".tar.xz"))
(patches '())
(sha256
(base32
"1p67pnp2ca5przx2s45r8m55dcn6f5hsm0l4s1zp7mglkf4r4n18")))))
(inputs
`(,@(%boot0-inputs)
("expat" ,expat-sans-tests))) ;remove OpenSSL, zlib, etc.
(native-inputs '()) ;and pkg-config
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
,@(substitute-keyword-arguments (package-arguments python-minimal)
;; Disable features that cannot be built at this stage.
((#:configure-flags _ ''())
`(list "--without-ensurepip"
"--without-threads"))
;; Clear #:make-flags, such that changes to the regular
;; Python package won't interfere with this one.
((#:make-flags _ ''()) ''())
((#:phases phases)
`(modify-phases ,phases
(add-before 'configure 'disable-modules
(lambda _
(substitute* "setup.py"
;; Disable ctypes, since it requires libffi.
(("extensions\\.append\\(ctypes\\)") "")
;; Prevent the 'ossaudiodev' extension from being
;; built, since it requires Linux headers.
(("'linux', ") ""))
#t))
(delete 'set-TZDIR)))
((#:tests? _ #f) #f))))))
(define ld-wrapper-boot0
(mlambda ()
;; We need this so binaries on Hurd will have libmachuser and libhurduser
;; in their RUNPATH, otherwise validate-runpath will fail.
(make-ld-wrapper "ld-wrapper-boot0"
#:target boot-triplet
#:binutils binutils-boot0
#:guile %bootstrap-guile
#:bash (car (assoc-ref (%boot0-inputs) "bash"))
#:guile-for-build %bootstrap-guile)))
(define (%boot1-inputs)
;; 2nd stage inputs.
`(("gcc" ,gcc-boot0)
("ld-wrapper-cross" ,(ld-wrapper-boot0))
("binutils-cross" ,binutils-boot0)
,@(alist-delete "binutils" (%boot0-inputs))))
(define glibc-final-with-bootstrap-bash
;; The final libc, "cross-built". If everything went well, the resulting
;; store path has no dependencies. Actually, the really-final libc is
;; built just below; the only difference is that this one uses the
;; bootstrap Bash.
(package
(inherit glibc)
(name "glibc-intermediate")
(source (bootstrap-origin (package-source glibc)))
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
,@(substitute-keyword-arguments (package-arguments glibc)
((#:configure-flags flags)
`(append (list ,(string-append "--host=" (boot-triplet))
,(string-append "--build="
(nix-system->gnu-triplet)))
,flags))
((#:phases phases)
`(modify-phases ,phases
(add-before 'configure 'pre-configure
(lambda* (#:key inputs #:allow-other-keys)
;; Don't clobber CPATH with the bootstrap libc.
(setenv "NATIVE_CPATH" (getenv "CPATH"))
(unsetenv "CPATH")
;; Tell 'libpthread' where to find 'libihash' on Hurd systems.
,@(if (hurd-triplet? (%current-system))
`((substitute* "libpthread/Makefile"
(("LDLIBS-pthread.so =.*")
(string-append "LDLIBS-pthread.so = "
(assoc-ref %build-inputs "kernel-headers")
"/lib/libihash.a\n"))))
'())
;; 'rpcgen' needs native libc headers to be built.
(substitute* "sunrpc/Makefile"
(("sunrpc-CPPFLAGS =.*" all)
(string-append "CPATH = $(NATIVE_CPATH)\n"
"export CPATH\n"
all "\n")))
#t)))))))
(propagated-inputs `(("kernel-headers" ,(kernel-headers-boot0))))
(native-inputs
`(("bison" ,bison-boot0)
("texinfo" ,texinfo-boot0)
("perl" ,perl-boot0)
("python" ,python-boot0)))
(inputs
`( ;; The boot inputs. That includes the bootstrap libc. We don't want
;; it in $CPATH, hence the 'pre-configure' phase above.
,@(%boot1-inputs)
;; A native MiG is needed to build Glibc on Hurd.
,@(if (hurd-triplet? (%current-system))
`(("mig" ,mig-boot0))
'())
;; A native GCC is needed to build `cross-rpcgen'.
("native-gcc" ,@(assoc-ref (%boot0-inputs) "gcc"))
;; Here, we use the bootstrap Bash, which is not satisfactory
;; because we don't want to depend on bootstrap tools.
("static-bash" ,@(assoc-ref (%boot0-inputs) "bash"))))))
(define (cross-gcc-wrapper gcc binutils glibc bash)
"Return a wrapper for the pseudo-cross toolchain GCC/BINUTILS/GLIBC
that makes it available under the native tool names."
(package (inherit gcc)
(name (string-append (package-name gcc) "-wrapped"))
(source #f)
(build-system trivial-build-system)
(outputs '("out"))
(arguments
`(#:guile ,%bootstrap-guile
#:modules ((guix build utils))
#:builder (begin
(use-modules (guix build utils))
(let* ((binutils (assoc-ref %build-inputs "binutils"))
(gcc (assoc-ref %build-inputs "gcc"))
(libc (assoc-ref %build-inputs "libc"))
(bash (assoc-ref %build-inputs "bash"))
(out (assoc-ref %outputs "out"))
(bindir (string-append out "/bin"))
(triplet ,(boot-triplet)))
(define (wrap-program program)
;; GCC-BOOT0 is a libc-less cross-compiler, so it
;; needs to be told where to find the crt files and
;; the dynamic linker.
(call-with-output-file program
(lambda (p)
(format p "#!~a/bin/bash
exec ~a/bin/~a-~a -B~a/lib -Wl,-dynamic-linker -Wl,~a/~a \"$@\"~%"
bash
gcc triplet program
libc libc
,(glibc-dynamic-linker))))
(chmod program #o555))
(mkdir-p bindir)
(with-directory-excursion bindir
(for-each (lambda (tool)
(symlink (string-append binutils "/bin/"
triplet "-" tool)
tool))
'("ar" "ranlib"))
(for-each wrap-program '("gcc" "g++")))
#t))))
(native-inputs
`(("binutils" ,binutils)
("gcc" ,gcc)
("libc" ,glibc)
("bash" ,bash)))
(inputs '())))
(define (gcc-boot0-intermediate-wrapped)
;; Make the cross-tools GCC-BOOT0 and BINUTILS-BOOT0 available under the
;; non-cross names.
(cross-gcc-wrapper gcc-boot0 binutils-boot0
glibc-final-with-bootstrap-bash
(car (assoc-ref (%boot1-inputs) "bash"))))
(define static-bash-for-glibc
;; A statically-linked Bash to be used by GLIBC-FINAL in system(3) & co.
(package
(inherit static-bash)
(source (bootstrap-origin (package-source static-bash)))
(inputs `(("gcc" ,(gcc-boot0-intermediate-wrapped))
("libc" ,glibc-final-with-bootstrap-bash)
("libc:static" ,glibc-final-with-bootstrap-bash "static")
,@(fold alist-delete (%boot1-inputs)
'("gcc" "libc"))))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
,@(substitute-keyword-arguments (package-arguments static-bash)
((#:configure-flags flags '())
;; Add a '-L' flag so that the pseudo-cross-ld of
;; BINUTILS-BOOT0 can find libc.a.
`(append ,flags
(list (string-append "LDFLAGS=-static -L"
(assoc-ref %build-inputs
"libc:static")
"/lib")))))))))
(define gettext-boot0
;; A minimal gettext used during bootstrap.
(package
(inherit gettext-minimal)
(name "gettext-boot0")
;; Newer versions of GNU gettext depends on libxml2 and ncurses. To
;; simplify the dependency chain, we stick to this version here.
(version "0.19.8.1")
(source (origin
(method url-fetch)
(uri (string-append "mirror://gnu/gettext/gettext-"
version ".tar.gz"))
(sha256
(base32
"0hsw28f9q9xaggjlsdp2qmbp2rbd1mp0njzan2ld9kiqwkq2m57z"))))
(inputs (%boot1-inputs)) ;zero dependencies
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:tests? #f
#:phases (modify-phases %standard-phases
;; Build only the tools.
(add-after 'unpack 'chdir
(lambda _
(chdir "gettext-tools")
#t))
;; Some test programs require pthreads, which we don't have.
(add-before 'configure 'no-test-programs
(lambda _
(substitute* "tests/Makefile.in"
(("^PROGRAMS =.*$")
"PROGRAMS =\n"))
#t)))))))
(define glibc-final
;; The final glibc, which embeds the statically-linked Bash built above.
;; Use 'package/inherit' so we get the 'replacement' of 'glibc', if any.
(package/inherit
glibc
(name "glibc")
(source (bootstrap-origin (package-source glibc)))
(inputs `(("static-bash" ,static-bash-for-glibc)
,@(alist-delete
"static-bash"
(package-inputs glibc-final-with-bootstrap-bash))))
;; This time we need 'msgfmt' to install all the libc.mo files.
(native-inputs `(,@(package-native-inputs glibc-final-with-bootstrap-bash)
("gettext" ,gettext-boot0)))
(propagated-inputs
(package-propagated-inputs glibc-final-with-bootstrap-bash))
;; The final libc only refers to itself, but the 'debug' output contains
;; references to GCC-BOOT0 and to the Linux headers. XXX: Would be great
;; if 'allowed-references' were per-output.
(arguments
`(#:allowed-references
,(cons* `(,gcc-boot0 "lib") (kernel-headers-boot0)
static-bash-for-glibc
(package-outputs glibc-final-with-bootstrap-bash))
,@(package-arguments glibc-final-with-bootstrap-bash)))))
(define (gcc-boot0-wrapped)
;; Make the cross-tools GCC-BOOT0 and BINUTILS-BOOT0 available under the
;; non-cross names.
(cross-gcc-wrapper gcc-boot0 binutils-boot0 glibc-final
(car (assoc-ref (%boot1-inputs) "bash"))))
(define (%boot2-inputs)
;; 3rd stage inputs.
`(("libc" ,glibc-final)
("libc:static" ,glibc-final "static")
("gcc" ,(gcc-boot0-wrapped))
,@(fold alist-delete (%boot1-inputs) '("libc" "gcc" "linux-libre-headers"))))
(define binutils-final
(package
(inherit binutils)
(source (bootstrap-origin (package-source binutils)))
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
#:allowed-references ("out" ,glibc-final)
,@(package-arguments binutils)))
(inputs (%boot2-inputs))))
(define libstdc++
;; Intermediate libstdc++ that will allow us to build the final GCC
;; (remember that GCC-BOOT0 cannot build libstdc++.)
(let ((lib (make-libstdc++ gcc)))
(package
(inherit lib)
(source (bootstrap-origin (package-source lib)))
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
#:allowed-references ("out")
;; XXX: libstdc++.so NEEDs ld.so for some reason.
#:validate-runpath? #f
;; All of the package arguments from 'make-libstdc++
;; except for the configure-flags.
,@(package-arguments lib)
#:configure-flags `("--disable-shared"
"--disable-libstdcxx-dual-abi"
"--disable-libstdcxx-threads"
"--disable-libstdcxx-pch"
,(string-append "--with-gxx-include-dir="
(assoc-ref %outputs "out")
"/include"))))
(outputs '("out"))
(inputs (%boot2-inputs))
(synopsis "GNU C++ standard library (intermediate)"))))
(define zlib-final
;; Zlib used by GCC-FINAL.
(package
(inherit zlib)
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
#:allowed-references ("out" ,glibc-final)
,@(package-arguments zlib)))
(inputs (%boot2-inputs))))
(define ld-wrapper-boot3
(mlambda ()
;; A linker wrapper that uses the bootstrap Guile.
(make-ld-wrapper "ld-wrapper-boot3"
#:binutils binutils-final
#:guile %bootstrap-guile
#:bash (car (assoc-ref (%boot2-inputs) "bash"))
#:guile-for-build %bootstrap-guile)))
(define gcc-final
;; The final GCC.
(package (inherit gcc-boot0)
(name "gcc")
;; XXX: Currently #:allowed-references applies to all the outputs but the
;; "debug" output contains disallowed references, notably
;; linux-libre-headers. Disable the debugging output to work around that.
(outputs (delete "debug" (package-outputs gcc-boot0)))
(arguments
`(#:guile ,%bootstrap-guile
#:implicit-inputs? #f
#:allowed-references ("out" "lib" ,zlib-final
,glibc-final ,static-bash-for-glibc)
;; Things like libasan.so and libstdc++.so NEED ld.so for some
;; reason, but it is not in their RUNPATH. This is a false
;; positive, so turn it off.
#:validate-runpath? #f
,@(substitute-keyword-arguments (package-arguments gcc)
((#:make-flags flags)
;; Since $LIBRARY_PATH is not honored, add the relevant flags.
`(let ((zlib (assoc-ref %build-inputs "zlib")))
(map (lambda (flag)
(if (string-prefix? "LDFLAGS=" flag)
(string-append flag " -L"
(assoc-ref %build-inputs "libstdc++")
"/lib -L" zlib "/lib -Wl,-rpath="
zlib "/lib")
flag))
,flags)))
;; Build again GMP & co. within GCC's build process, because it's hard
;; to do outside (because GCC-BOOT0 is a cross-compiler, and thus
;; doesn't honor $LIBRARY_PATH, which breaks `gnu-build-system'.)
((#:phases phases)
`(modify-phases ,phases
(add-after 'unpack 'unpack-gmp&co
(lambda* (#:key inputs #:allow-other-keys)
(let ((gmp (assoc-ref %build-inputs "gmp-source"))
(mpfr (assoc-ref %build-inputs "mpfr-source"))
(mpc (assoc-ref %build-inputs "mpc-source")))
;; To reduce the set of pre-built bootstrap inputs, build
;; GMP & co. from GCC.
(for-each (lambda (source)
(invoke "tar" "xvf" source))
(list gmp mpfr mpc))
;; Create symlinks like `gmp' -> `gmp-x.y.z'.
,@(map (lambda (lib)
;; Drop trailing letters, as gmp-6.0.0a unpacks
;; into gmp-6.0.0.
`(symlink ,(string-trim-right
(package-full-name lib "-")
char-set:letter)
,(package-name lib)))
(list gmp-6.0 mpfr mpc))
#t)))
(add-before 'configure 'treat-glibc-as-system-header
(lambda* (#:key inputs #:allow-other-keys)
(let ((libc (assoc-ref inputs "libc")))
;; Make sure Glibc is treated as a "system header" so
;; #include_next does the right thing.
(for-each (lambda (var)
(setenv var (string-append libc "/include")))
'("C_INCLUDE_PATH" "CPLUS_INCLUDE_PATH"))
#t))))))))
;; This time we want Texinfo, so we get the manual. Add
;; STATIC-BASH-FOR-GLIBC so that it's used in the final shebangs of
;; scripts such as 'mkheaders' and 'fixinc.sh' (XXX: who cares about these
;; scripts?).
(native-inputs `(("texinfo" ,texinfo-boot0)
("perl" ,perl-boot0) ;for manpages
("static-bash" ,static-bash-for-glibc)
,@(package-native-inputs gcc-boot0)))
(inputs `(("gmp-source" ,(bootstrap-origin (package-source gmp-6.0)))
("mpfr-source" ,(package-source mpfr))
("mpc-source" ,(package-source mpc))
("ld-wrapper" ,(ld-wrapper-boot3))
("binutils" ,binutils-final)
("libstdc++" ,libstdc++)
("zlib" ,zlib-final)
,@(%boot2-inputs)))))
(define (%boot3-inputs)
;; 4th stage inputs.
`(("gcc" ,gcc-final)
("ld-wrapper" ,(ld-wrapper-boot3))
,@(alist-delete "gcc" (%boot2-inputs))))
(define bash-final
;; Link with `-static-libgcc' to make sure we don't retain a reference
;; to the bootstrap GCC. Use "bash-minimal" to avoid an extra dependency
;; on Readline and ncurses.
(let ((bash (static-libgcc-package bash-minimal)))
(package
(inherit bash)
(source (bootstrap-origin (package-source bash)))
(inputs (%boot3-inputs))
(arguments
`(#:implicit-inputs? #f
#:guile ,%bootstrap-guile
#:disallowed-references ,(assoc-ref (%boot3-inputs) "coreutils&co")
,@(package-arguments bash))))))
(define (%boot4-inputs)
;; Now use the final Bash.
`(("bash" ,bash-final)
,@(alist-delete "bash" (%boot3-inputs))))
(define with-boot4
(package-with-explicit-inputs %boot4-inputs %bootstrap-guile))
(define-public guile-final
;; This package must be public because other modules refer to it. However,
;; mark it as hidden so that 'fold-packages' ignores it.
(with-boot4 (hidden-package
(package-with-bootstrap-guile guile-2.2/fixed))))
(define glibc-utf8-locales-final
;; Now that we have GUILE-FINAL, build the UTF-8 locales. They are needed
;; by the build processes afterwards so their 'scm_to_locale_string' works
;; with the full range of Unicode codepoints (remember
;; 'scm_to_locale_string' is called every time a string is passed to a C
;; function.)
(package
(inherit glibc-utf8-locales)
(native-inputs
`(("glibc" ,glibc-final)
("gzip" ,(with-boot4 gzip))))))
(define-public ld-wrapper
;; The final 'ld' wrapper, which uses the final Guile and Binutils.
(make-ld-wrapper "ld-wrapper"
#:binutils binutils-final
#:guile guile-final
#:bash bash-final))
(define (%boot5-inputs)
;; Now with UTF-8 locales. Remember that the bootstrap binaries were built
;; with an older libc, which cannot load the new locale format. See
;; <https://lists.gnu.org/archive/html/guix-devel/2015-08/msg00737.html>.
`(("locales" ,glibc-utf8-locales-final)
,@(%boot4-inputs)))
(define with-boot5
(package-with-explicit-inputs %boot5-inputs))
(define gnu-make-final
;; The final GNU Make, which uses the final Guile.
;; FIXME: This is a mistake: we shouldn't be propagating GUILE-FINAL to
;; PKG-CONFIG.
;; TODO: Fix that on the next rebuild cycle.
(let ((pkg-config (package
(inherit pkg-config)
(inputs `(("guile" ,guile-final)
,@(%boot5-inputs)))
(arguments
`(#:implicit-inputs? #f
,@(package-arguments pkg-config))))))
(package
(inherit (package-with-bootstrap-guile gnu-make))
(inputs `(("guile" ,guile-final)
,@(%boot5-inputs)))
(native-inputs `(("pkg-config" ,pkg-config)))
(arguments
`(#:implicit-inputs? #f
,@(package-arguments gnu-make))))))
(define coreutils-final
;; The final Coreutils. Treat them specially because some packages, such as
;; Findutils, keep a reference to the Coreutils they were built with.
(with-boot5 (package-with-bootstrap-guile coreutils)
;; Use the final Guile, linked against the
;; final libc with working iconv, so that
;; 'substitute*' works well when touching
;; test files in Gettext.
))
(define grep-final
;; The final grep. Gzip holds a reference to it (via zgrep), so it must be
;; built before gzip.
(let ((grep (with-boot5 (package-with-bootstrap-guile grep))))
(package/inherit grep
(inputs (alist-delete "pcre" (package-inputs grep)))
(native-inputs `(("perl" ,perl-boot0))))))
(define (%boot6-inputs)
;; Now use the final Coreutils.
`(("coreutils" ,coreutils-final)
("grep" ,grep-final)
,@(%boot5-inputs)))
(define with-boot6
(package-with-explicit-inputs %boot6-inputs))
(define sed-final
;; The final sed.
(let ((sed (with-boot6 (package-with-bootstrap-guile sed))))
(package/inherit sed (native-inputs `(("perl" ,perl-boot0))))))
(define-public %final-inputs
;; Final derivations used as implicit inputs by 'gnu-build-system'. We
;; still use 'package-with-bootstrap-guile' so that the bootstrap tools are
;; used for origins that have patches, thereby avoiding circular
;; dependencies.
(let ((finalize (compose with-boot6
package-with-bootstrap-guile)))
`(,@(map (match-lambda
((name package)
(list name (finalize package))))
`(("tar" ,tar)
("gzip" ,gzip)
("bzip2" ,bzip2)
("xz" ,xz)
("file" ,file)
("diffutils" ,diffutils)
("patch" ,patch)
("findutils" ,findutils)
("gawk" ,gawk)))
("sed" ,sed-final)
("grep" ,grep-final)
("coreutils" ,coreutils-final)
("make" ,gnu-make-final)
("bash" ,bash-final)
("ld-wrapper" ,ld-wrapper)
("binutils" ,binutils-final)
("gcc" ,gcc-final)
("libc" ,glibc-final)
("libc:static" ,glibc-final "static")
("locales" ,glibc-utf8-locales-final))))
(define-public canonical-package
(let ((name->package (fold (lambda (input result)
(match input
((_ package . outputs)
(vhash-cons (package-full-name package)
package result))))
vlist-null
`(("guile" ,guile-final)
,@%final-inputs))))
(lambda (package)
"Return the 'canonical' variant of PACKAGE---i.e., if PACKAGE is one of
the implicit inputs of 'gnu-build-system', return that one, otherwise return
PACKAGE.
The goal is to avoid duplication in cases like GUILE-FINAL vs. GUILE-2.2,
COREUTILS-FINAL vs. COREUTILS, etc."
;; XXX: This doesn't handle dependencies of the final inputs, such as
;; libunistring, GMP, etc.
(match (vhash-assoc (package-full-name package) name->package)
((_ . canon)
;; In general we want CANON, except if we're cross-compiling: CANON
;; uses explicit inputs, so it is "anchored" in the bootstrapped
;; process, with dependencies on things that cannot be
;; cross-compiled.
(if (%current-target-system)
package
canon))
(_ package)))))
;;;
;;; GCC toolchain.
;;;
;; Using the following procedure, a gcc toolchain targeting glibc-2.27 can be
;; instantiated like this:
;;
;; (define-public gcc-glibc-2.27-toolchain
;; (make-gcc-toolchain gcc glibc-2.27))
(define* (make-gcc-toolchain gcc
#:optional
(libc #f))
"Return a complete toolchain for GCC. If LIBC is specified, target that libc."
(let ((gcc (if libc (make-gcc-libc gcc libc) gcc))
(libc (if libc libc glibc-final)))
(package
(name (string-append (package-name gcc) "-toolchain"))
(version (package-version gcc))
(source #f)
(build-system trivial-build-system)
(arguments
'(#:modules ((guix build union))
#:builder (begin
(use-modules (ice-9 match)
(srfi srfi-26)
(guix build union))
(let ((out (assoc-ref %outputs "out")))
(match %build-inputs
(((names . directories) ...)
(union-build out directories)))
(union-build (assoc-ref %outputs "debug")
(list (assoc-ref %build-inputs
"libc-debug")))
(union-build (assoc-ref %outputs "static")
(list (assoc-ref %build-inputs
"libc-static")))
#t))))
(native-search-paths (package-native-search-paths gcc))
(search-paths (package-search-paths gcc))
(license (package-license gcc))
(synopsis "Complete GCC tool chain for C/C++ development")
(description
"This package provides a complete GCC tool chain for C/C++ development to
be installed in user profiles. This includes GCC, as well as libc (headers
an d binaries, plus debugging symbols in the @code{debug} output), and Binutils.")
(home-page "https://gcc.gnu.org/")
(outputs '("out" "debug" "static"))
;; The main raison d'être of this "meta-package" is (1) to conveniently
;; install everything that we need, and (2) to make sure ld-wrapper comes
;; before Binutils' ld in the user's profile.
(inputs `(("gcc" ,gcc)
("ld-wrapper" ,(car (assoc-ref %final-inputs "ld-wrapper")))
("binutils" ,binutils-final)
("libc" ,libc)
("libc-debug" ,libc "debug")
("libc-static" ,libc "static"))))))
(define-public gcc-toolchain
(make-gcc-toolchain gcc-final))
(define-public gcc-toolchain-4.8
(make-gcc-toolchain gcc-4.8))
(define-public gcc-toolchain-4.9
(make-gcc-toolchain gcc-4.9))
(define-public gcc-toolchain-5
(make-gcc-toolchain gcc-5))
(define-public gcc-toolchain-6
(make-gcc-toolchain gcc-6))
(define-public gcc-toolchain-7
gcc-toolchain)
(define-public gcc-toolchain-8
(make-gcc-toolchain gcc-8))
(define-public gcc-toolchain-9
(make-gcc-toolchain gcc-9))
;;; commencement.scm ends here