#!/bin/bash # Run all the steps needed to build a system image from scratch. # The default set of stages run by this script is (in order): # download, host-tools, simple-cross-compiler, root-filesystem, # native-compiler, system-image. # That sanitizes the host build environment and builds a cross compiler, # cross compiles a root filesystem and a native toolchain for the target, # and finally packages the root filesystem up into a system image bootable # by qemu. # The optional cross-compiler stage (after simple-cross-compiler but before # root-filesystem) creates a more powerful and portable cross compiler # that can be used to cross compile more stuff (if you're into that sort of # thing). To enable that: # CROSS_COMPILER_HOST=i686 ./build.sh $TARGET # Where "i686" is whichever target you want the new cross compiler to run on. # The simplest set of stages (if you run them yourself) is: # download, simple-cross-compiler, root-filesystem, system-image. # If this script was run with no arguments, list available architectures test ! -z $2 && setglobal REBUILD = $2 && test ! -e "$2".sh && echo "no stage $2" && exit 1 if test $Argc -lt 1 || test $Argc -gt 2 || test ! -e sources/targets/"$1" { echo echo "Usage: $0 TARGET [REBUILD_FROM_STAGE]" echo echo "Supported architectures:" ls sources/targets echo echo "Build stages:" sed -n 's/#.*//;s@.*[.]/\([^.]*\)[.]sh.*@\1@p' $0 | uniq | xargs echo echo exit 1 } setglobal ARCH = $1 # Use environment variables persistently set in the config file. test -e config && source config # Allow the output directory to be overridden. This hasn't been tested in # forever and probably doesn't work. test -z $BUILD && setglobal BUILD = '"build'" # Very simple dependency tracking: skip stages that have already been done # (because the tarball they create is already there). # If you need to rebuild a stage (and everything after it), delete its # tarball out of "build" and re-run build.sh. proc not_already { test $AGAIN == $1 && return 0 test $REBUILD == $1 && zap $1 if test -f "$BUILD/$1-$ARCH.tar.gz" { echo "=== Skipping $1-$ARCH (already there)" return 1 } return 0 } proc zap { for i in [@Argv] { rm -f "$BUILD/$i-$ARCH.tar.gz" } } # If $AFTER set, skip stages until we match $AFTER to implement $2="start here" proc do_stage { setglobal STAGE = $1 shift if test $AFTER == $STAGE { unset AFTER } else { time ./"$STAGE".sh @Argv || exit 1 } } # The first two stages (download.sh and host-tools.sh) are architecture # independent. In order to allow multiple builds in parallel, re-running # them after they've already completed must be a safe NOP. # Download source code. If tarballs already there, verify sha1sums and # delete/redownload if they don't match (to handle interrupted partial # download). do_stage download # Build host tools. This populates a single directory with every command the # build needs, so we can ditch the host's $PATH afterwards. if test -z $NO_HOST_TOOLS { do_stage host-tools } # Do we need to build the simple cross compiler? if test -z $MY_CROSS_PATH && not_already simple-cross-compiler { # If we need to build cross compiler, assume root filesystem is stale. zap root-filesystem cross-compiler native-compiler do_stage simple-cross-compiler $ARCH } # Optionally, we can build a more capable statically linked compiler via # canadian cross. (It's more powerful than we need here, but if you're going # to use the cross compiler in other contexts this is probably what you want.) if test -z $MY_CROSS_PATH && test ! -z $CROSS_COMPILER_HOST && not_already cross-compiler { zap root-filesystem native-compiler # Build the host compiler if necessary if env ARCH=$CROSS_COMPILER_HOST not_already simple-cross-compiler { do_stage simple-cross-compiler $CROSS_COMPILER_HOST } do_stage cross-compiler $ARCH } if ! grep -q KARCH= sources/targets/"$ARCH" { echo no KARCH in $1, stopping here } # Build the basic root filesystem. if not_already root-filesystem { do_stage root-filesystem $ARCH } # Build a native compiler. It's statically linked by default so it can # run on an arbitrary host system. # Not trying to build nommu native compilers for the moment. if test -z $MY_CROSS_PATH && ! grep -q ELF2FLT sources/targets/"$ARCH" && not_already native-compiler { do_stage native-compiler $ARCH } # Package it all up into something qemu can boot. Like host-tools.sh, # this is always called and handles its own dependencies internally. do_stage system-image $ARCH