boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

stage3-rebuild.sh (10369B)


      1 #!/bin/sh
      2 ## scripts/stage3-rebuild.sh — drive the tcc-boot1 / tcc-boot2 chain
      3 ## inside a busybox container, consuming stage 2's tcc-boot0-mes.
      4 ##
      5 ## Mirrors live-bootstrap's pass1.kaem (steps/tcc-0.9.26) chain:
      6 ##   tcc-boot0-mes (= tcc-boot0 slot)
      7 ##     → rebuild libc → tcc-boot1
      8 ##     → rebuild libc → tcc-boot2  (= "final 0.9.26")
      9 ##
     10 ## Each rebuild compiles the **real**, unflattened tcc-0.9.26 sources
     11 ## (the patched tree at $WORK/tcc-0.9.26-1147-gee75a10c) using the
     12 ## previous-stage tcc, with the full live-bootstrap define set
     13 ## (HAVE_FLOAT, HAVE_BITFIELD, HAVE_SETJMP added on top of the stage 1
     14 ## flatten set).
     15 ##
     16 ## Pre-condition:
     17 ##   build/amd64/vendor/tcc/tcc-boot0-mes
     18 ##   build/amd64/vendor/tcc/stage3-input/   (staged by stage 2)
     19 ##   build/amd64/vendor/tcc/tcc-0.9.26-1147-gee75a10c/  (patched, from stage 1)
     20 ##   build/amd64/vendor/tcc/mes-0.27.1/                 (from stage 2)
     21 ##
     22 ## Container: docker.io/library/busybox:musl on linux/amd64.
     23 ## Tools used inside: busybox sh + tcc-boot0-mes (which provides its own
     24 ## preprocessor, assembler, linker, and `-ar`).
     25 ##
     26 ## Status: stage 3 cannot complete on macOS arm64 hosts today — Issue §3
     27 ## (tcc-boot0-mes segfaults at startup under QEMU x86_64) blocks the
     28 ## very first step. The script is correct; it will run end-to-end on
     29 ## native x86_64 hardware or once a tcc 0.9.28rc backport patches the
     30 ## prologue/_DYNAMIC issues. The failure is reported clearly so the
     31 ## blocker is visible.
     32 ##
     33 ## Usage:
     34 ##   scripts/stage3-rebuild.sh [--arch X86_64]
     35 
     36 set -eu
     37 
     38 ARCH=X86_64
     39 while [ $# -gt 0 ]; do
     40     case "$1" in
     41         --arch)    ARCH=$2; shift 2 ;;
     42         -h|--help) sed -n 's/^## \{0,1\}//p' "$0"; exit 0 ;;
     43         *) echo "unknown arg: $1" >&2; exit 2 ;;
     44     esac
     45 done
     46 
     47 if [ "$ARCH" != "X86_64" ]; then
     48     echo "stage3 currently only supports X86_64" >&2
     49     exit 2
     50 fi
     51 MES_ARCH=x86_64
     52 BOOT_ARCH=amd64
     53 
     54 ROOT=$(cd "$(dirname "$0")/.." && pwd)
     55 WORK=$ROOT/build/$BOOT_ARCH/vendor/tcc
     56 TCC_PKG=tcc-0.9.26-1147-gee75a10c
     57 MES_PKG=mes-0.27.1
     58 
     59 [ -x "$WORK/tcc-boot0-mes" ]      || { echo "missing $WORK/tcc-boot0-mes — run stage2-alpine.sh" >&2; exit 1; }
     60 [ -d "$WORK/stage3-input" ]       || { echo "missing $WORK/stage3-input — run stage2-alpine.sh" >&2; exit 1; }
     61 [ -d "$WORK/$TCC_PKG" ]           || { echo "missing $WORK/$TCC_PKG — run stage1-flatten.sh" >&2; exit 1; }
     62 [ -d "$WORK/$MES_PKG" ]           || { echo "missing $WORK/$MES_PKG — run stage2-alpine.sh" >&2; exit 1; }
     63 command -v podman >/dev/null 2>&1 || { echo "podman required" >&2; exit 2; }
     64 
     65 echo "=== stage 3: tcc-boot1 / tcc-boot2 via busybox:musl ==="
     66 echo "(Issue §3 may block on macOS arm64 / QEMU; native x86_64 expected to succeed)"
     67 
     68 podman run --rm -i --platform linux/amd64 \
     69     -v "$ROOT":/work -w /work \
     70     docker.io/library/busybox:musl sh -s "$ARCH" "$MES_ARCH" "$TCC_PKG" "$MES_PKG" "$BOOT_ARCH" <<'CONTAINER_SCRIPT'
     71 set -eu
     72 ARCH=$1
     73 MES_ARCH=$2
     74 TCC_PKG=$3
     75 MES_PKG=$4
     76 BOOT_ARCH=$5
     77 WORK=/work/build/$BOOT_ARCH/vendor/tcc
     78 
     79 # --- install tcc-boot0-mes + mes libc bits at baked-in paths --------
     80 mkdir -p /lib/tcc /include/mes /bin
     81 cp "$WORK/stage3-input/lib/libc.a"        /lib/libc.a
     82 cp "$WORK/stage3-input/lib/crt1.o"        /lib/crt1.o
     83 cp "$WORK/stage3-input/lib/crtn.o"        /lib/crtn.o
     84 cp "$WORK/stage3-input/lib/crti.o"        /lib/crti.o
     85 cp "$WORK/stage3-input/lib/tcc/libtcc1.a" /lib/tcc/libtcc1.a
     86 cp -r "$WORK/stage3-input/include/mes/."  /include/mes/
     87 
     88 TCC=$WORK/tcc-boot0-mes
     89 
     90 echo "--- tcc-boot0-mes -version (smoke; Issue §3 may SEGV here) ---"
     91 "$TCC" -version
     92 
     93 INC_MES=/include/mes
     94 TCC_DEFS_BUILD="-D BOOTSTRAP=1 \
     95     -D HAVE_FLOAT=1 \
     96     -D HAVE_BITFIELD=1 \
     97     -D HAVE_LONG_LONG=1 \
     98     -D HAVE_SETJMP=1 \
     99     -D TCC_TARGET_${ARCH}=1 \
    100     -D CONFIG_TCCDIR=\"/lib/tcc\" \
    101     -D CONFIG_TCC_CRTPREFIX=\"/lib\" \
    102     -D CONFIG_TCC_ELFINTERP=\"/mes/loader\" \
    103     -D CONFIG_TCC_LIBPATHS=\"/lib:/lib/tcc\" \
    104     -D CONFIG_TCC_SYSINCLUDEPATHS=\"/include/mes\" \
    105     -D TCC_LIBGCC=\"/lib/libc.a\" \
    106     -D TCC_LIBTCC1=\"libtcc1.a\" \
    107     -D CONFIG_TCCBOOT=1 \
    108     -D CONFIG_TCC_STATIC=1 \
    109     -D CONFIG_USE_LIBGCC=1 \
    110     -D TCC_VERSION=\"0.9.26\" \
    111     -D ONE_SOURCE=1"
    112 
    113 # Helper: rebuild mes libc with the given tcc binary, install to /lib + /lib/tcc.
    114 # Mirrors pass1.kaem's "Recompile libc" block after each tcc-bootN.
    115 rebuild_libc() {
    116     cc=$1
    117     label=$2
    118     echo "--- $label: rebuilding mes libc ---"
    119     cd "$WORK/$MES_PKG"
    120     "$cc" -c -D HAVE_CONFIG_H=1 -I include -I include/linux/$MES_ARCH \
    121         -o /lib/crt1.o lib/linux/$MES_ARCH-mes-gcc/crt1.c
    122 
    123     "$cc" -c -D HAVE_CONFIG_H=1 -D HAVE_LONG_LONG=1 -D HAVE_FLOAT=1 \
    124         -I include -I include/linux/$MES_ARCH \
    125         -o /tmp/libtcc1.o lib/libtcc1.c
    126     "$cc" -ar cr /lib/tcc/libtcc1.a /tmp/libtcc1.o
    127 
    128     # libc.a: same per-file approach as stage 2 (Issue §2 workaround).
    129     rm -rf /tmp/objs && mkdir -p /tmp/objs
    130     cd lib
    131     OBJS=
    132     for f in $ALL_LIBC_FILES; do
    133         name=$(echo "$f" | tr / _)
    134         o=/tmp/objs/${name%.c}.o
    135         "$cc" -c -D HAVE_CONFIG_H=1 -I ../include -I ../include/linux/$MES_ARCH \
    136             -o "$o" "$f"
    137         OBJS="$OBJS $o"
    138     done
    139     "$cc" -ar cr /lib/libc.a $OBJS
    140     cd "$WORK/$MES_PKG/.."
    141 }
    142 
    143 # Helper: compile tcc.c (real, unflattened) into a new tcc binary.
    144 # Mirrors pass1.kaem's tcc-boot0/1/2 invocations.
    145 build_tcc() {
    146     cc=$1
    147     out=$2
    148     echo "--- $out: $cc compiling real tcc.c ---"
    149     cd "$WORK/$TCC_PKG"
    150     eval "\"$cc\" -g -static -o \"$WORK/$out\" \
    151         $TCC_DEFS_BUILD \
    152         -I . -I $INC_MES \
    153         -L . -L /lib \
    154         tcc.c"
    155     "$WORK/$out" -version
    156 }
    157 
    158 # Same canonical mes libc list as stage 2 + pass1.kaem.
    159 ALL_LIBC_FILES="ctype/isalnum.c ctype/isalpha.c ctype/isascii.c ctype/iscntrl.c \
    160 ctype/isdigit.c ctype/isgraph.c ctype/islower.c ctype/isnumber.c \
    161 ctype/isprint.c ctype/ispunct.c ctype/isspace.c ctype/isupper.c \
    162 ctype/isxdigit.c ctype/tolower.c ctype/toupper.c \
    163 dirent/closedir.c dirent/__getdirentries.c dirent/opendir.c \
    164 linux/readdir.c linux/access.c linux/brk.c linux/chdir.c linux/chmod.c \
    165 linux/clock_gettime.c linux/close.c linux/dup2.c linux/dup.c linux/execve.c \
    166 linux/fcntl.c linux/fork.c linux/fsync.c linux/fstat.c linux/_getcwd.c \
    167 linux/getdents.c linux/getegid.c linux/geteuid.c linux/getgid.c linux/getpid.c \
    168 linux/getppid.c linux/getrusage.c linux/gettimeofday.c linux/getuid.c \
    169 linux/ioctl.c linux/ioctl3.c linux/kill.c linux/link.c linux/lseek.c \
    170 linux/lstat.c linux/malloc.c linux/mkdir.c linux/mknod.c linux/nanosleep.c \
    171 linux/_open3.c linux/pipe.c linux/_read.c linux/readlink.c linux/rename.c \
    172 linux/rmdir.c linux/setgid.c linux/settimer.c linux/setuid.c linux/signal.c \
    173 linux/sigprogmask.c linux/symlink.c linux/stat.c linux/time.c linux/unlink.c \
    174 linux/waitpid.c linux/wait4.c \
    175 linux/${MES_ARCH}-mes-gcc/_exit.c linux/${MES_ARCH}-mes-gcc/syscall.c \
    176 linux/${MES_ARCH}-mes-gcc/_write.c \
    177 math/ceil.c math/fabs.c math/floor.c \
    178 mes/abtod.c mes/abtol.c mes/__assert_fail.c mes/assert_msg.c \
    179 mes/__buffered_read.c mes/__init_io.c mes/cast.c mes/dtoab.c \
    180 mes/eputc.c mes/eputs.c mes/fdgetc.c mes/fdgets.c mes/fdputc.c mes/fdputs.c \
    181 mes/fdungetc.c mes/globals.c mes/itoa.c mes/ltoab.c mes/ltoa.c \
    182 mes/__mes_debug.c mes/mes_open.c mes/ntoab.c mes/oputc.c mes/oputs.c \
    183 mes/search-path.c mes/ultoa.c mes/utoa.c \
    184 posix/alarm.c posix/buffered-read.c posix/execl.c posix/execlp.c \
    185 posix/execv.c posix/execvp.c posix/getcwd.c posix/getenv.c posix/isatty.c \
    186 posix/mktemp.c posix/open.c posix/pathconf.c posix/raise.c posix/sbrk.c \
    187 posix/setenv.c posix/sleep.c posix/unsetenv.c posix/wait.c posix/write.c \
    188 stdio/clearerr.c stdio/fclose.c stdio/fdopen.c stdio/feof.c stdio/ferror.c \
    189 stdio/fflush.c stdio/fgetc.c stdio/fgets.c stdio/fileno.c stdio/fopen.c \
    190 stdio/fprintf.c stdio/fputc.c stdio/fputs.c stdio/fread.c stdio/freopen.c \
    191 stdio/fscanf.c stdio/fseek.c stdio/ftell.c stdio/fwrite.c stdio/getc.c \
    192 stdio/getchar.c stdio/perror.c stdio/printf.c stdio/putc.c stdio/putchar.c \
    193 stdio/remove.c stdio/snprintf.c stdio/sprintf.c stdio/sscanf.c stdio/ungetc.c \
    194 stdio/vfprintf.c stdio/vfscanf.c stdio/vprintf.c stdio/vsnprintf.c \
    195 stdio/vsprintf.c stdio/vsscanf.c \
    196 stdlib/abort.c stdlib/abs.c stdlib/alloca.c stdlib/atexit.c stdlib/atof.c \
    197 stdlib/atoi.c stdlib/atol.c stdlib/calloc.c stdlib/__exit.c stdlib/exit.c \
    198 stdlib/free.c stdlib/mbstowcs.c stdlib/puts.c stdlib/qsort.c stdlib/realloc.c \
    199 stdlib/strtod.c stdlib/strtof.c stdlib/strtol.c stdlib/strtold.c \
    200 stdlib/strtoll.c stdlib/strtoul.c stdlib/strtoull.c \
    201 string/bcmp.c string/bcopy.c string/bzero.c string/index.c string/memchr.c \
    202 string/memcmp.c string/memcpy.c string/memmem.c string/memmove.c string/memset.c \
    203 string/rindex.c string/strcat.c string/strchr.c string/strcmp.c string/strcpy.c \
    204 string/strcspn.c string/strdup.c string/strerror.c string/strlen.c \
    205 string/strlwr.c string/strncat.c string/strncmp.c string/strncpy.c \
    206 string/strpbrk.c string/strrchr.c string/strspn.c string/strstr.c string/strupr.c \
    207 stub/atan2.c stub/bsearch.c stub/chown.c stub/__cleanup.c stub/cos.c \
    208 stub/ctime.c stub/exp.c stub/fpurge.c stub/freadahead.c stub/frexp.c \
    209 stub/getgrgid.c stub/getgrnam.c stub/getlogin.c stub/getpgid.c stub/getpgrp.c \
    210 stub/getpwnam.c stub/getpwuid.c stub/gmtime.c stub/ldexp.c stub/localtime.c \
    211 stub/log.c stub/mktime.c stub/modf.c stub/mprotect.c stub/pclose.c \
    212 stub/popen.c stub/pow.c stub/putenv.c stub/rand.c stub/realpath.c stub/rewind.c \
    213 stub/setbuf.c stub/setgrent.c stub/setlocale.c stub/setvbuf.c stub/sigaction.c \
    214 stub/sigaddset.c stub/sigblock.c stub/sigdelset.c stub/sigemptyset.c \
    215 stub/sigsetmask.c stub/sin.c stub/sys_siglist.c stub/system.c stub/sqrt.c \
    216 stub/strftime.c stub/times.c stub/ttyname.c stub/umask.c stub/utime.c \
    217 ${MES_ARCH}-mes-gcc/setjmp.c"
    218 
    219 # --- Pass 1: tcc-boot0-mes -> tcc-boot1 -----------------------------
    220 rebuild_libc "$TCC" "tcc-boot0-mes"
    221 build_tcc    "$TCC" "tcc-boot1"
    222 
    223 # --- Pass 2: tcc-boot1 -> tcc-boot2 (final 0.9.26) ------------------
    224 TCC=$WORK/tcc-boot1
    225 rebuild_libc "$TCC" "tcc-boot1"
    226 build_tcc    "$TCC" "tcc-boot2"
    227 
    228 echo
    229 echo "=== stage 3: tcc-boot2 is the final 0.9.26 build ==="
    230 ls -la "$WORK/tcc-boot1" "$WORK/tcc-boot2"
    231 CONTAINER_SCRIPT
    232 
    233 echo
    234 echo "=== stage 3 artifacts ==="
    235 ls -la "$WORK/tcc-boot1" "$WORK/tcc-boot2" 2>/dev/null || \
    236     echo "(stage 3 did not complete — see container output above; likely Issue §3)"