RustForge

foundry

Foundry OS: the operating system built on the Rustbelt kernel

foundry / ports / busybox / build.sh
3876 bytes ยท raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env bash
# Build busybox (one program that contains ~300 small Unix tools, called
# "applets") for Foundry OS:
#   1. unpack the cached tarball (with Python: no bzip2 program needed),
#   2. use the committed configuration ports/busybox/busybox.config (see
#      ports/busybox/README.md for what is switched off and why),
#   3. run busybox's Makefile with our compiler:
#        make CC=toolchain/foundry-cc LD=ld HOSTCC=gcc
# The result is ONE static-PIE program. It is installed as
# /usr/lib/busybox/busybox on the ext2 root, next to one symlink per applet
# (/usr/lib/busybox/awk -> busybox, ...), all OFF the default PATH, so the
# Foundry OS Rust tools stay the default. Run an applet as
#   busybox awk ...        (with /usr/lib/busybox/busybox spelled out)
# or as /usr/lib/busybox/awk ...
#
# Usage: ports/busybox/build.sh CACHE_DIR BUILD_DIR OUT_DIR
#   OUT_DIR/busybox is the program, OUT_DIR/applets.txt lists the applet
#   names, OUT_DIR/LICENSE is busybox's licence (GPL v2).
#
# Host needs (besides gcc and the musl sysroot): python3, and the Linux
# kernel's userspace headers in /usr/include/linux and /usr/include/asm
# (Debian/Ubuntu package linux-libc-dev). busybox includes a few of them
# (<linux/fs.h>, ...), and foundry-cc only searches the musl sysroot, so we
# copy them into BUILD_DIR/kernel-headers and add that with -isystem.
set -euo pipefail
HERE=$(cd "$(dirname "$0")" && pwd)
ROOT=$(cd "$HERE/../.." && pwd)
CACHE=$(realpath "$1") BUILD=$(realpath -m "$2") OUTDIR=$(realpath -m "$3")
read -r _ file < "$HERE/busybox.sha256"
rm -rf "$BUILD" && mkdir -p "$BUILD"
python3 "$HERE/untar.py" "$CACHE/$file" "$BUILD"
src=$BUILD/${file%.tar.bz2}

# Linux userspace headers. -L copies the files that symlinks point at.
kh=$BUILD/kernel-headers
asm=/usr/include/$(gcc -print-multiarch 2>/dev/null)/asm
[ -d "$asm" ] || asm=/usr/include/asm
for d in /usr/include/linux /usr/include/asm-generic "$asm"; do
    [ -d "$d" ] || { echo "[busybox] missing $d: install linux-libc-dev"; exit 1; }
done
mkdir -p "$kh"
cp -rL /usr/include/linux /usr/include/asm-generic "$kh/"
cp -rL "$asm" "$kh/asm"
[ -d /usr/include/mtd ] && cp -rL /usr/include/mtd "$kh/"

# busybox's build pipes its config through `bzip2 -1` (for `busybox
# --show-config`-style data). No bzip2 on the host? Use a tiny Python one.
if ! command -v bzip2 > /dev/null; then
    mkdir -p "$BUILD/hostbin"
    cp "$HERE/bzip2-shim.py" "$BUILD/hostbin/bzip2"
    chmod +x "$BUILD/hostbin/bzip2"
    export PATH=$BUILD/hostbin:$PATH
fi

cd "$src"
cp "$HERE/busybox.config" .config
# oldconfig fills in nothing new if busybox.config matches this version;
# if it had to ask anything, the committed file is stale.
{ yes "" || true; } | make oldconfig > "$BUILD/oldconfig.log" 2>&1
if ! diff -q <(grep '^CONFIG_\|is not set' "$HERE/busybox.config") \
             <(grep '^CONFIG_\|is not set' .config) > /dev/null; then
    echo "[busybox] busybox.config is out of date for this busybox version:"
    echo "          rerun ports/busybox/mkconfig.sh and commit the result"; exit 1
fi
# LD=ld: busybox first links each directory with `ld -r`, which can't be
# combined with foundry-cc's -static-pie. The final link still uses CC.
make -j"$(nproc)" CC="$ROOT/toolchain/foundry-cc" LD=ld HOSTCC=gcc \
     EXTRA_CFLAGS="-isystem $kh" busybox busybox.links > "$BUILD/make.log" 2>&1 ||
    { tail -30 "$BUILD/make.log"; exit 1; }
if readelf -l busybox | grep -q INTERP; then
    echo "[busybox] busybox has a PT_INTERP: not a static-PIE"; exit 1
fi
rm -rf "$OUTDIR" && mkdir -p "$OUTDIR"
cp busybox "$OUTDIR/busybox"
strip --strip-debug "$OUTDIR/busybox"
sed 's,.*/,,' busybox.links | sort > "$OUTDIR/applets.txt"   # /bin/ls -> ls
cp LICENSE "$OUTDIR/LICENSE"
echo "[busybox] built $OUTDIR/busybox: $(wc -l < "$OUTDIR/applets.txt") applets, $(stat -c %s "$OUTDIR/busybox") bytes, static-PIE"