make-root.sh (7777B)
- #!/bin/sh
- # bootstrap-initrd: Linux initrd to bootstrap from a small binary seed
- # SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- # SPDX-License-Identifier: MPL-2.0
- tarballs="
- lolibc-96b2b7e.tar.gz
- loksh-7.6.tar.gz
- yacc-oyacc-6.6.tar.gz
- utils-std-0.0.1.tar.gz
- pdpmake-2.0.1.tgz
- nawk-20240728.tar.gz
- bzip2-bzip2-1.0.8.tar.gz
- zlib-1.3.1.tar.gz
- pigz-2.8.tar.gz
- heirloom-070715.tar.bz2
- heirloom-devtools-070527.tar.bz2
- sbase-b30fb568.tar.gz
- "
- local_files="
- init.sh
- src/ls-stub.c
- src/grep-stub.c
- src/cp-stub.c
- src/getty-stub.c
- src/mount-stub.c
- "
- distfiles="
- make-4.4.1.tar.gz
- xz-5.6.2.tar.gz
- lua-5.4.6.tar.gz
- pkgconf-2.3.0.tar.gz
- iproute2-6.6.0.tar.gz
- skalibs-2.14.2.0.tar.gz
- mdevd-0.1.6.4.tar.gz
- bearssl-0.6.tar.gz
- tiny-curl-8.4.0.tar.gz
- cacert-2024-03-11.pem
- gettext-tiny-0.3.2.tar.gz
- git-2.45.2.tar.gz
- e2fsprogs-1.47.1.tar.gz
- "
- local_distfiles="
- extras/make.sh
- extras/xz.sh
- extras/lua.sh
- extras/pkgconf.sh
- extras/iproute2.sh
- extras/skalibs.sh
- extras/mdevd.sh
- extras/bearssl.sh
- extras/tiny-curl.sh
- extras/gettext-tiny.sh
- extras/git.sh
- extras/e2fsprogs.sh
- extras-build-all.sh
- "
- WORKDIR="$(dirname "$0")"
- WORKDIR="$(realpath "$WORKDIR")"
- . "$WORKDIR/common.sh"
- : ${ALPINE_ARCH:=x86_64}
- name_base="bootstrap-initrd"
- out_base="${WORKDIR}/${name_base}/${ALPINE_ARCH}"
- gen_loksh_tcc_h() {
- cd loksh-*/ || die
- printf 'char *loksh_tcc_cmd[] = {'
- # -DSMALL to not need ncurses
- printf '"%s", ' /usr/bin/tcc -o /bin/loksh \
- -D_GNU_SOURCE -DEMACS -DVI -DSMALL -DHAVE_STRLCPY -DHAVE_STRLCAT -DHAVE_ISSETUGID \
- -I ../lolibc-*/include/ *.c \
- ../lolibc-*/sys_signame.c ../lolibc-*/strsignals.c ../lolibc-*/unvis.c ../lolibc-*/vis.c ../lolibc-*/strtonum.c
- printf '0};'
- cd "$out_base" || die "Failed: cd $out_base"
- }
- set -e
- sha512sum -c distfiles.SHA512SUM
- if test -e "$out_base"; then
- rm -fr "$out_base"
- fi
- mkdir -p "$out_base" || die "Failed: mkdir $out_base"
- cd "$out_base" || die "Failed: cd $out_base"
- mkdir -p src
- cd "${out_base}/src"
- for i in $tarballs; do
- tar xof "${WORKDIR}/distfiles/$i" || die "Failed extracting $i"
- done
- cd -
- for i in $local_files; do
- cp "${WORKDIR}/$i" ./"$i" || die "Failed copying $i"
- done
- if ! test "${EXCLUDE_EXTRAS:+y}" = "y"; then
- mkdir -p ./extras
- for i in $local_distfiles; do
- cp "${WORKDIR}/$i" ./"$i" || die "Failed copying $i"
- done
- mkdir -p ./distfiles
- for i in $distfiles
- do
- cp "${WORKDIR}/distfiles/$i" ./distfiles/ || die "Failed copying $i"
- done
- fi
- deblob
- mkdir -p dev proc sys etc usr/bin var/empty || die "Failed creating base directories"
- ln -s /proc/mounts etc/mtab || die "Failed symlink for /etc/mtab"
- ln -s bin sbin
- ln -s usr/lib lib
- ln -s usr/bin bin
- ln -s usr/bin sbin
- mkdir -m 777 tmp
- cat >etc/passwd <<EOF
- root:x:0:0:root:/root:/bin/sh
- nobody:x:65534:65534:nobody:/var/empty:/bin/false
- EOF
- cat >etc/group <<EOF
- root:x:0:root
- nobody:x:65534:
- nogroup:x:65533:
- EOF
- for i in fd stderr stdin stdout; do
- ln -fs proc/self/$i dev/$i
- done
- cp "${WORKDIR}/init.c" ./init || die "copying init"
- sed -i '1i#!/usr/bin/tcc -run' ./init || die "failed adding tcc shebang to init"
- chmod 755 init || die "init chmod"
- cp -p "${WORKDIR}/ar-stub.sh" ./bin/ar
- for apk in $APKS_main $APKS_testing
- do
- tar xof "${WORKDIR}/distfiles/$apk.${ALPINE_ARCH}" --exclude '.*'
- done
- # Allows to shave off ~9.1M from the binary seed
- rm usr/lib/libc.a
- cd "${out_base}/src"
- # For CLOCK_MONOTONIC and clock_gettime
- sed -i -e '1a#include <time.h>' loksh-*/c_sh.c || die "Failed patching loksh/c_sh.c"
- # For u_char
- sed -i -e '1a#include <sys/types.h>' loksh-*/edit.c || die "Failed patching loksh/c_sh.c"
- # For int64_t
- sed -i -e '1a#include <stdint.h>' loksh-*/table.h || die "Failed patching loksh/table.h"
- sed -i -e '1a#include <limits.h>' -e 's;_PW_NAME_LEN;LOGIN_NAME_MAX;' loksh-*/main.c || die "Failed patching loksh/main.c"
- ln -s loksh "${out_base}/bin/sh"
- gen_loksh_tcc_h > loksh_tcc.h
- cd "${out_base}/src"
- oyacc=$(echo ./yacc-oyacc-*/)
- cat >"${oyacc}/config.h" <<EOF
- // __dead and __dead2 are absent in musl
- #define __dead __attribute__((__no_return__))
- // HAVE_PROGNAME: Absent in musl
- #define HAVE_ASPRINTF
- // HAVE_PLEDGE: Absent in musl
- #define HAVE_REALLOCARRAY
- #define HAVE_STRLCPY
- EOF
- sed -i -e 's;bzip2-shared;bzip2;' bzip2-*/Makefile-libbz2_so || die "Failed patching /bzip2-*/Makefile-libbz2_so"
- sed -i -e 's;all: libbz2.a;all: libbz2.so;' -e 's;bzip2: libbz2.a;bzip2: libbz2.so;' bzip2-*/Makefile || die "Failed patching /bzip2-*/Makefile"
- rm bzip2-*/sample* || die "Failed removing sample bzip2 files"
- patch -p0 <"${WORKDIR}/zlib-1.3.1_no_staticlib.patch"
- patch -p0 <"${WORKDIR}/zlib-1.3.1-use-LDFLAGS-in-configure.patch"
- patch -p0 <"${WORKDIR}/zlib-1.3.1-use-LDFLAGS-in-configure_no_gcc.patch"
- rm zlib-*/doc/crc-doc.1.0.pdf || die "Failed removing zlib crc-doc.1.0.pdf"
- rm zlib-*/crc32.h || die "Failed removing autogenerated zlib-*/crc32.h"
- rm -r zlib-*/examples/ || die "Failed removing zlib-*/examples/"
- rm -r zlib-*/contrib/ || die "Failed removing zlib-*/contrib/"
- sed -i 's;^clean: minizip-clean;clean:;' zlib-*/Makefile.in || die "Failed disabling minizip cleanup"
- sed -i \
- -e 's;INSTALL=.*;INSTALL=install;' \
- -e 's;PREFIX=.*;PREFIX=/usr;;' \
- -e 's;STRIP=.*;STRIP=true;' \
- -e 's;#?AR=.*;AR ?= ar;' \
- -e 's;RANLIB=.*;RANLIB ?= ranlib;' \
- -e 's;YACC=.*;YACC ?= yacc;' \
- heirloom-devtools-*/mk.config \
- || die "Failed configuring heirloom-devtools"
- # pdpmake-1.4.3+ consider them invalid "macros"
- sed -i \
- -e '/^\.c\.o:/s/;/\n\t/' \
- heirloom-devtools-*/lex/Makefile.mk heirloom-devtools-*/m4/Makefile.mk \
- || die "Failed patching .c.o: inferred targets in heirloom-devtools"
- # - maninst Fails to create parent dir, just noop it, we don't have man anyway
- # -e 's;MANINST =.*;MANINST = $(SHELL) ../build/maninst.sh;' \
- # - Turns out tcc comes with an ar(1)
- # -e 's;LCOMMON =.*;LCOMMON = ../libcommon/*.c;' \
- sed -i \
- -e 's;DEFBIN =.*;DEFBIN = /bin;' \
- -e 's;DEFSBIN =.*;DEFSBIN = /bin;' \
- -e 's;STRIP =.*;STRIP = true;' \
- -e 's;SPELLHIST =.*;SPELLHIST = /dev/null;' \
- -e 's;UCBINST =.*;UCBINST = install;' \
- -e 's;MANINST =.*;MANINST = true;' \
- heirloom-0*/build/mk.config \
- || die "Failed configuring heirloom (toolchest)"
- sed -i \
- -e 's;__GLIBC__;__linux__;' \
- -e '/#define getdents/s;^;//;' \
- heirloom-070715/libcommon/getdir.c || die "Failed fixing heirloom libcommon for musl"
- sed -i \
- -e 's;#ifdef _AIX;#if defined(_AIX) || defined(__linux__);' \
- -e '/static int utf8/avoid writerr(struct oblok *op, int count, int written) {}' \
- heirloom-070715/tar/tar.c || die "Failed fixing heirloom tar for musl"
- sed -i \
- -e 's;#ifdef _AIX;#if defined(_AIX) || defined(__linux__);' \
- heirloom-070715/find/find.c || die "Failed fixing heirloom find for musl"
- sed -i -e 's;libwchar.a: fake;libwchar.a:;' heirloom-070715/libwchar/Makefile.mk || die
- sed -i -e 's;getdir.o regexpr.o gmatch.o;getdir.o gmatch.o;' heirloom-*/libcommon/Makefile.mk || die
- rm -r heirloom-*/libuxre heirloom-*/libcommon/regexp.h || die
- rm -r pigz-*/zopfli || die
- rm -r heirloom-devtools-*/make heirloom-devtools-*/sccs || die
- for i in cpio spell mail nawk oawk
- do
- rm -r heirloom-0*/$i || die
- done
- rm -r awk-*/testdir || die
- cd "${out_base}/"
- deblob -n -j "${WORKDIR}"/make-root-deblob.json || die
- if command -v jq >/dev/null; then
- jq --raw-output0 '.[].path' "${WORKDIR}"/make-root-deblob.json \
- | xargs -0 du -bach \
- | sort -h
- elif command -v qjs >/dev/null; then
- <"${WORKDIR}"/make-root-deblob.json \
- qjs --std \
- -e 'let deblob_raw = std.in.readAsString(); let deblob = JSON.parse(deblob_raw); deblob.forEach((e) => {std.printf("%s\0", e.path);})' \
- | xargs -0 du -bach \
- | sort -h
- else
- echo "make-root: Command 'jq' and 'qjs' not found. Not going to list sizes of blobs" 1>&2
- fi
- cd "${WORKDIR}"