#!/bin/sh set -e abuild_opts="-r" if [ "$1" = "-k" ] || [ "$1" = "--keep" ]; then abuild_opts="$abuild_opts -k" shift fi TARGET_ARCH="$1" SUDO_APK=abuild-apk shift # optional cross build packages #: ${KERNEL_PKG=linux-firmware linux-lts} #: ${COMPILER_PKG=libffi brotli libev c-ares cunit nghttp2 libidn2 libunistring libpsl curl libssh2 libxml2 pax-utils llvm15 community/ghc llvm20 rust community/go} # FIXME: Maybe subdivide into ghc, rust, and go stuff : ${MKINITFS=libcap-ng ncurses readline sqlite util-linux libaio lvm2 popt xz json-c argon2 cryptsetup kmod lddtree mkinitfs} #: ${OPENSSH=openssh} if [ -z "$TARGET_ARCH" ]; then program=$(basename $0) cat <&2 } if [ ! -d "$CBUILDROOT" ]; then msg "Creating sysroot in $CBUILDROOT" mkdir -p "$CBUILDROOT/etc/apk/keys" # /etc/apk/keys and ~/.abuild/ can contain files with the same names. # if that is the case, cp will abort copying and fail. Then on the next # run of the bootstrap script, 1) the keys are not in the sysroot and # 2) the apk database is not initialized the sysroot # Thus it's unusable at that point and needs to be deleted manually. cp -a /etc/apk/keys/* "$CBUILDROOT/etc/apk/keys" cp -a ~/.abuild/*.pub "$CBUILDROOT/etc/apk/keys" ${SUDO_APK} add --quiet --initdb --arch $TARGET_ARCH --root $CBUILDROOT fi msg "Building cross-compiler" # Build and install cross binutils (--with-sysroot) CTARGET=$TARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname binutils) abuild $abuild_opts if ! CHOST=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild up2date 2>/dev/null; then # C-library headers for target CHOST=$TARGET_ARCH BOOTSTRAP=nocc APKBUILD=$(apkbuildname musl) abuild $abuild_opts # Minimal cross GCC EXTRADEPENDS_HOST="musl-dev" \ CTARGET=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname gcc) abuild $abuild_opts # Cross build bootstrap C-library for the target EXTRADEPENDS_BUILD="gcc-pass2-$TARGET_ARCH" \ CHOST=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild $abuild_opts fi # Build libucontext without docs and pkgconfig file as a dependency for gcc-gdc EXTRADEPENDS_BUILD="gcc-pass2-$TARGET_ARCH" \ EXTRADEPENDS_TARGET="musl musl-dev" \ CHOST=$TARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname libucontext) abuild $abuild_opts # Full cross GCC EXTRADEPENDS_TARGET="musl musl-dev libucontext-dev" \ CTARGET=$TARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname gcc) abuild $abuild_opts # Cross build-base CTARGET=$TARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname build-base) abuild $abuild_opts msg "Cross building base system" # Implicit dependencies for early targets EXTRADEPENDS_TARGET="libgcc libstdc++ musl-dev" # On a few architectures like riscv64 we need to account for # gcc requiring -ltomic to be set explicitly if a C[++]11 program # uses atomics (e.g. #include ): # https://github.com/riscv/riscv-gnu-toolchain/issues/183#issuecomment-253721765 # The reason gcc itself is needed is because .so is in that package, # not in libatomic. if [ "$TARGET_ARCH" = "riscv64" ]; then NEEDS_LIBATOMIC="yes" fi if [ $# -eq 0 ]; then set -- fortify-headers linux-headers musl pkgconf zlib \ openssl ca-certificates libmd \ gmp mpfr4 mpc1 isl26 libucontext zstd binutils gcc \ bsd-compat-headers libbsd busybox make \ apk-tools file \ libcap openrc alpine-conf alpine-baselayout alpine-keys alpine-base patch build-base \ attr acl fakeroot tar \ lzip abuild \ $OPENSSH \ $MKINITFS \ $COMPILER_PKG \ $KERNEL_PKG fi for PKG; do if [ "$NEEDS_LIBATOMIC" = "yes" ]; then EXTRADEPENDS_BUILD="libatomic gcc-$TARGET_ARCH g++-$TARGET_ARCH" fi EXTRADEPENDS_TARGET="$EXTRADEPENDS_TARGET" EXTRADEPENDS_BUILD="$EXTRADEPENDS_BUILD" \ CHOST=$TARGET_ARCH BOOTSTRAP=bootimage APKBUILD=$(apkbuildname $PKG) abuild $abuild_opts case "$PKG" in fortify-headers) # Additional implicit dependencies once built EXTRADEPENDS_TARGET="$EXTRADEPENDS_TARGET $PKG" ;; gcc) if [ "$NEEDS_LIBATOMIC" = "yes" ]; then EXTRADEPENDS_TARGET="libatomic gcc $EXTRADEPENDS_TARGET" fi ;; build-base) # After build-base, that alone is sufficient dependency in the target EXTRADEPENDS_TARGET="busybox $PKG" ;; esac done