#!/bin/sh
set -eu
version_mes = 0.22
version_mescc_tools = 1.0.1
version_nyacc = 0.99.3
version_linux = 4.14
version_binutils = 2.20.1
version_gcc = 4.9.4
version_gmp = 4.3.2
version_mpfr = 2.4.2
version_mpc = 1.0.3
version_musl = 1.2.1
version_busybox = 1.31.1
export MAKEFLAGS = " -j ${ NPROC :- $( getconf _NPROCESSORS_ONLN) } "
system = system
dir_root = " $PWD "
dir_sources = " $dir_root /sources "
dir_install = " $dir_root / $system "
mkdir -p build && cd build
rm -rf " mes- $version_mes "
tar xf " $dir_sources /mes- $version_mes .tar.gz "
( cd " mes- $version_mes "
tar xf " $dir_sources /mescc-tools-Release_ $version_mescc_tools .tar.gz "
tar xf " $dir_sources /nyacc- $version_nyacc .tar.gz "
mv " mescc-tools-Release_ $version_mescc_tools " mescc-tools
mv " nyacc- $version_nyacc " nyacc
cp -a mescc-tools mescc-tools-target
make -C mescc-tools M1 hex2 blood-elf COMMIT =
export PATH = " $PWD /mescc-tools/bin: $PATH "
# First, we build a native mes, "mes-gcc".
# This allows us to cross-build everything on systems that mes doesn't support.
gcc -w -O2 -std= gnu99 -fcommon -lrt -o mes-gcc -DMES_VERSION= '""' -DSYSTEM_LIBC= 1 -Iinclude \
lib/mes/eputs.c \
lib/mes/fdgetc.c \
lib/mes/fdputc.c \
lib/mes/fdputs.c \
lib/mes/fdungetc.c \
lib/mes/itoa.c \
lib/mes/mes_open.c \
lib/mes/ntoab.c \
src/gc.c \
src/hash.c \
src/lib.c \
src/math.c \
src/mes.c \
src/module.c \
src/posix.c \
src/reader.c \
src/string.c \
src/struct.c \
src/vector.c
# This version of mes messes doesn't have a proper getopt...
# TODO: Fix this (somehow) and make the patch unnecessary.
sed -i -e 's/ -nostdlib/ --nostdlib/' \
-e 's/ -lc/ -l c/' \
build-aux/bootstrap.sh.in
# Use this to build mes and its libc for the target
CC = true guile_site_dir = " $PWD /nyacc/module " sh configure.sh --host= x86-linux-mes
CC = " $PWD /scripts/mescc " MES = " $PWD /mes-gcc " sh bootstrap.sh
# Install mes
install -Dm755 bin/mes " $dir_install /mes/bin/mes "
# Build tools with mes to obtain reproducible outputs
make -C mescc-tools-target M1 hex2 blood-elf COMMIT = \
CC = " $PWD /scripts/mescc " MES = " $PWD /mes-gcc " MES_PREFIX = "../" \
GUILE_LOAD_PATH = "../module" CFLAGS = '-L ../lib -L ../mescc-lib -l c+tcc'
install -Dm755 mescc-tools-target/bin/M1 " $dir_install /mes/bin/M1 "
install -Dm755 mescc-tools-target/bin/hex2 " $dir_install /mes/bin/hex2 "
install -Dm755 mescc-tools-target/bin/blood-elf " $dir_install /mes/bin/blood-elf "
)
rm -rf " linux- $version_linux "
tar xf " $dir_sources /linux- $version_linux .tar.gz "
( cd " linux- $version_linux "
make mrproper
make ARCH = x86 INSTALL_HDR_PATH = " $dir_install /sources/linux-headers " headers_install
find " $dir_install /sources/linux-headers " -type f ! -name "*.h" -exec rm { } +
)
# Build static busybox with musl
rm -rf " busybox- $version_busybox "
tar xf " $dir_sources /busybox- $version_busybox .tar.bz2 "
( cd " busybox- $version_busybox "
tar xf " $dir_sources /binutils- ${ version_binutils } a.tar.bz2 "
mv " binutils- $version_binutils " binutils
tar xf " $dir_sources /gcc- $version_gcc .tar.bz2 "
mv " gcc- $version_gcc " gcc
tar xf " $dir_sources /gmp- $version_gmp .tar.bz2 "
mv " gmp- $version_gmp " gcc/gmp
tar xf " $dir_sources /mpfr- $version_mpfr .tar.bz2 "
mv " mpfr- $version_mpfr " gcc/mpfr
tar xf " $dir_sources /mpc- $version_mpc .tar.gz "
mv " mpc- $version_mpc " gcc/mpc
tar xf " $dir_sources /musl- $version_musl .tar.gz "
mv " musl- $version_musl " musl
prefix = " $PWD /prefix "
export PATH = " $prefix /bin: $PATH "
# Fix requirement for mktemp, so it works with coreutils-5.0
if ! command -v mktemp 2> /dev/null; then
sed -i -e 's@$(mktemp tmp.XXXXXXXXXX)@/tmp/tmp.trylink@' scripts/trylink
fi
# Building a specific version of binutils+GCC, to make the results reproducible...
# GCC-4.6.4's results aren't reproducible across machines for some reason,
# so this bootstrap uses GCC-4.9.4. This increases the build time a little.
( cd binutils
CFLAGS = '-O2 -w -fcommon' ./configure \
--target= i686-bootstrap-linux-gnu \
--prefix= " $prefix " \
--with-sysroot= " $prefix " \
--disable-nls \
--disable-werror
make
make install
)
( cd gcc
mkdir build && cd build # Build breaks without a build directory
# Using --with-local-prefix=/ puts /include in the search path before
# /lib/gcc/.../include-fixed, avoiding some issues.
CFLAGS = '-O2 -w' CXXFLAGS = '-O2 -w' MAKEINFO = true ../configure \
--target= i686-bootstrap-linux-gnu \
--prefix= " $prefix " \
--with-sysroot= " $prefix " \
--with-local-prefix= / \
--with-host-libstdcxx= -lsupc++ \
--with-newlib \
--without-headers \
--disable-shared \
--disable-threads \
--disable-nls \
--enable-languages= c
make all-gcc all-target-libgcc
make install-gcc install-target-libgcc
)
# Musl provides a very small libc, that can be linked statically.
# It might be worthwhile to switch to uClibc in the future, as that's
# what's usually used for busybox. Might yield "cleaner" results.
cp -a " $dir_install /sources/linux-headers " prefix
( cd musl
./configure \
--host= i686-bootstrap-linux-gnu \
--prefix= " $PWD /../prefix " \
--disable-shared
make
make install
)
cp " $dir_root /busybox-config " .config
make CROSS_COMPILE = i686-bootstrap-linux-gnu- CONFIG_STATIC = y busybox
install -Dm755 busybox " $dir_install /bin/busybox "
install -Dm755 busybox_unstripped " $dir_install /bin/busybox_unstripped "
)
cd " $dir_install "
# Verify the built binaries
sha1sum -c " $dir_root /binaries.sha1 "
# Pack it up
find bin mes sources \( -type f -o -type l \) ! -path bin/busybox_unstripped | LC_ALL = C sort | xargs tar --mtime= @0 --numeric-owner --owner= 0 --group= 0 -cf binaries.tar
gzip -nv binaries.tar
# Clean up
cd " $dir_root "
rm -rf build