[Android Software/Hacking General [Developers Only]] osm0sis:
AIK Build Farm

I recently switched my Android Image Kitchen binary compiles from Native (on-device) to a neat little "AIK Build Farm" I wrote for use in Cygwin, so I thought I'd post the script in case it helps anyone else with cross-compiling. I put my Cygwin-to-Linux CCs and the NDK Standalone CCs (arm, x86 & mips; arm64, x86_64 & mips64, generated with e.g. $NDK_ROOT/build/tools/make-standalone-toolchain.sh --arch=arm64 --platform=android-21 --install-dir=aarch64-linux-android-r15c-api21-unified or $NDK_ROOT/build/tools/make_standalone_toolchain.py --arch arm64 --api 21 --stl gnustl --unified-headers --force --install-dir aarch64-linux-android-r15c-api21-unified) in ~/x-tools/, and have the sources for everything in ~/. Should easily translate to Linux if you add #!/sbin/sh or whatever, as well. Be sure to use at least platform android-8 for the arm NDK CC, and gcc-4.6 or 4.9 for x86 to avoid compiler warnings/errors. For macOS (Darwin) compiles I used osxcross and MacOSX10.7.sdk with a couple workarounds.

~/aik-build.sh:

#!/bin/bash
# fuϲk yes

# aik-build.sh
#
# osm0sis @ xda-developers
#
# requires (in addition to the default basic Ubuntu WSL2 packages):
# make, cmake, automake, autopoint, gettext, libtool, bison, flex, g++, gcc-multilib, g++-multilib, libssl-dev, libssl-dev:i386, libsdl2-dev
#
# ~/android-ndk-r15c and ~/x-tools/ NDK standalone toolchains (e.g. arm-linux-androideabi-r15c-api21-unified), osxcross darwin11

AIKHOME=$HOME;
XTOOLS=$AIKHOME/x-tools;
OSXCROSS=$AIKHOME/osxcross;
BUILD=$AIKHOME/AIK-build;

generic() {
local app cc define recipe;
app=$(echo $1 | cut -d/ -f1);
shift;
cd $app;
case $1 in
update)
git checkout master >/dev/null 2>&1;
echo -n "--- $app: ";
git pull origin;
return;
;;
config) return;;
esac;

case $OUTPUT in
linux*|macos*) ;;
*) recipe=static; define="-D__ANDROID_API__=21";;
esac;
cc=$CC;
if [ "$(ls *.cpp 2>/dev/null)" ]; then
case $CC in
gcc*) cc=${CC/gcc/g++};;
clang) cc=${CC/clang/clang++};;
esac;
fi;
CC="$cc" CFLAGS="$define" make $ARGS $recipe;
case $app in
*mkbootimg) mv -f *bootimg "$BUILD/$OUTPUT/";;
*) mv -f $app "$BUILD/$OUTPUT/$app";;
esac;
make $ARGS clean;
}

mkimage/dumpimage() {
local basecross cflags curtag dir includes ldflags libs savedpath sysroot;
case $1 in
update)
cd uboot*;
git fetch --tags >/dev/null;
curtag=$(git tag | grep -vE 'rc' | tail -n 1);
dir="uboot-$(echo $curtag | cut -c 2-)";
echo -n "--- mkimage/dumpimage: ";
if [ "$dir" != "$(basename $PWD)" -o "$FORCE" ]; then
echo "Checking out $curtag";
git reset -- . >/dev/null;
git clean -df >/dev/null;
git checkout -- .;
git checkout -f $curtag 2>&1 | tail -n 1;
# work around breakage on older make versions
sed -i 's/undefine MK_ARCH/override MK_ARCH =/' Makefile;
# undo broken former non-POSIX Cygwin/Windows changes
sed -i 's/HOSTCFLAGS\t+= -ansi/HOSTCFLAGS += $(CSTD_FLAG)/' Makefile;
# neuter setlocalversion to give us only the proper revision
sed -i "s/printf '\%s' -dirty/printf '\%s'/" scripts/setlocalversion;
# fix missing Cygwin, macOS and NDK includes/defines
sed -i 's;# include <byteswap.h>;# include <byteswap.h>\n#elif defined(__CYGWIN__)\n# include <linux/types.h>\n# include <linux/byteorder/swab.h>;' include/compiler.h;
sed -i 's|#ifdef __FreeBSD__|#ifdef __ANDROID__\ntypedef unsigned short ushort;\n#endif\n#ifdef __FreeBSD__|' include/compiler.h;
sed -i 's|#include <asm/posix_types.h>|#include <asm/posix_types.h>\n\n#ifndef __kernel_ulong_t\ntypedef long __kernel_long_t;\ntypedef unsigned long __kernel_ulong_t;\n#endif\n\n#ifndef __kernel_daddr_t\ntypedef int __kernel_daddr_t;\n#endif\n\n#ifndef __kernel_ino_t\ntypedef __kernel_ulong_t __kernel_ino_t;\n#endif|' include/linux/posix_types.h;
sed -i 's|malloc.h|stdlib.h|' lib/rsa/rsa-sign.c;
# work around missing macOS clock_gettime and CLOCK_MONOTONIC
wget -O tools/timing_mach.c https://raw.githubusercontent.com/ChisholmKyle/PosixMachTiming/master/src/timing_mach.c;
wget -O tools/timing_mach.h https://raw.githubusercontent.com/ChisholmKyle/PosixMachTiming/master/src/timing_mach.h;
sed -i 's|#include <version.h>|#include <version.h>\n\n#include "timing_mach.c"|' tools/image-host.c;
cd ..;
mv uboot* $dir;
else
echo "Already up to date.";
fi;
return;
;;
config)
cd uboot*;
echo "--- Configuring mkimage/dumpimage";
make sandbox_defconfig;
# disable unneeded options to avoid build errors and reduce binary size
sed -i 's|^CONFIG_CMD_NET=y|# CONFIG_CMD_NET is not set|' .config;
sed -i 's|^CONFIG_CMD_LOADS=y|# CONFIG_CMD_LOADS is not set|' .config;
sed -i 's|^CONFIG_EFI_LOADER=y|# CONFIG_EFI_LOADER is not set|' .config;
sed -i 's|^CONFIG_NETCONSOLE=y|# CONFIG_NETCONSOLE is not set|' .config;
sed -i 's|^CONFIG_TOOLS_MKEFICAPSULE=y|# CONFIG_TOOLS_MKEFICAPSULE is not set|' .config;
sed -i 's|^CONFIG_VIDEO_LOGO=y|# CONFIG_VIDEO_LOGO is not set|' .config;
return;
;;
esac;

cd uboot*;
export OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1;
savedpath="$PATH";
if [ "$CROSS_COMPILE" ]; then
export PATH="$(dirname $CROSS_COMPILE):$PATH";
# work around extra weird NDK stand-alone cross-compiler incompatibilities with U-Boot's KBuild
sysroot="$(dirname "$(dirname $CROSS_COMPILE)")"/sysroot;
fi;
cflags="-ffunction-sections -O3";
ldflags="-Wl,--gc-sections,-s";
case $OUTPUT in
linux*) ldflags="$ldflags -Wl,-ldl";;
macos*) cflags="$cflags -Wno-unused-command-line-argument -Wno-macro-redefined -fcommon"; ldflags="-Wl,-no_compact_unwind,-dead_strip,-lz";;
*) cflags="$cflags -D__ANDROID_API__=21"; ldflags="--sysroot=$sysroot -static $ldflags -Wl,-static";;
esac;
# use prebuilt NDK libraries and prebuilt macOS libraries + includes sourced from MacPorts darwin10 openssl11-1.1.1s i386/x86_64
case $OUTPUT in
linux*) libs=.;;
*) libs="../libcrypto/$ARCH-prebuilt"; includes="-I../libcrypto/$ARCH-prebuilt/include"; basecross=$(basename $CROSS_COMPILE);;
esac;
# work around missing CONFIG_FUZZ after sandbox_defconfig triggering "Restart config..." on macOS
grep -q '# CONFIG_FUZZ ' .config || sed -i 's|^# CONFIG_ASAN is not set|# CONFIG_ASAN is not set\n# CONFIG_FUZZ is not set|' .config;
if [ "$ARGS" = --silent ]; then
make $ARGS CROSS_BUILD_TOOLS=y HOSTCC="gcc -Wno-char-subscripts" CC="${basecross}${CC} $cflags $ldflags $includes -L$libs" tools-only >/dev/null 2>&1;
else
make $ARGS CROSS_BUILD_TOOLS=y HOSTCC="gcc -Wno-char-subscripts" CC="${basecross}${CC} $cflags $ldflags $includes -L$libs" tools-only;
fi;
mv -f tools/mkimage "$BUILD/$OUTPUT/mkimage";
mv -f tools/dumpimage "$BUILD/$OUTPUT/dumpimage";
make $ARGS clean;
export PATH="$savedpath";
unset OSXCROSS_NO_INCLUDE_PATH_WARNINGS;
}

futility() {
local define libs recipe;
case $1 in
update)
cd futility;
git checkout master >/dev/null 2>&1;
echo -n "--- futility: ";
git pull origin;
return;
;;
config) return;;
esac;

cd futility;
case $OUTPUT in
linux*|macos*) ;;
*) recipe=static; define="-D__ANDROID_API__=21";;
esac;
# use prebuilt NDK libraries and prebuilt macOS libraries + includes sourced from MacPorts darwin10 openssl11-1.1.1s i386/x86_64
case $OUTPUT in
linux*) libs=.;;
*) libs="../libcrypto/$ARCH-prebuilt";;
esac;
if [ "$ARGS" = --silent ]; then
CFLAGS="$define" LDFLAGS="-L$libs" make $ARGS $recipe >/dev/null 2>&1;
else
CFLAGS="$define" LDFLAGS="-L$libs" make $ARGS $recipe;
fi;
mv -f futility "$BUILD/$OUTPUT/futility";
make $ARGS clean;
}

blobpack/blobunpack() {
local cflags ldflags;
cd blobtools;
case $1 in
update)
git checkout master >/dev/null 2>&1;
echo -n "--- blobtools: ";
git pull origin;
return;
;;
config) return;;
esac;

cflags="-I. -Ishared -Wall -ggdb -ffunction-sections -O3";
ldflags="-Wl,--gc-sections";
case $OUTPUT in
linux*) ;;
macos*) ldflags="-Wl,-dead_strip";;
*) cflags="$cflags -D__ANDROID_API__=21"; ldflags="$ldflags -static -s";;
esac;
if [ "$ARGS" = --silent ]; then
make $ARGS CC="${CROSS_COMPILE}${CC}" CFLAGS="$cflags" LDFLAGS="$ldflags" >/dev/null 2>&1;
else
make $ARGS CC="${CROSS_COMPILE}${CC}" CFLAGS="$cflags" LDFLAGS="$ldflags";
fi;
mv -f blobpack "$BUILD/$OUTPUT/blobpack";
mv -f blobunpack "$BUILD/$OUTPUT/blobunpack";
make $ARGS clean;
}

rkcrc() {
local cflags ldflags;
cd rkflashtool;
case $1 in
update)
git checkout master >/dev/null 2>&1;
echo -n "--- rkflashtool: ";
git pull origin;
return;
;;
config) return;;
esac;

cflags="-ffunction-sections -O3";
ldflags="-Wl,--gc-sections -s";
case $OUTPUT in
linux*) ;;
macos*) ldflags="-Wl,-dead_strip";;
*) cflags="$cflags -D__ANDROID_API__=21"; ldflags="$ldflags -static";;
esac;
make $ARGS CC="${CROSS_COMPILE}${CC}" CROSSPREFIX=$CROSS_COMPILE CFLAGS="$cflags" LDFLAGS="$ldflags" rkcrc;
mv -f rkcrc "$BUILD/$OUTPUT/rkcrc";
make $ARGS clean;
}

lokitool() {
local cflags ldflags;
cd lokitool;
case $1 in
update)
git checkout master >/dev/null 2>&1;
echo -n "--- lokitool: ";
git pull origin;
return;
;;
config) return;;
esac;

cflags="-ffunction-sections -O3";
ldflags="-Wl,--gc-sections -s";
case $OUTPUT in
linux*) ;;
macos*) ldflags="-Wl,-dead_strip";;
*) cflags="$cflags -D__ANDROID_API__=21"; ldflags="$ldflags -static";;
esac;
make $ARGS CC="${CROSS_COMPILE}${CC}" CC_STRIP="${CROSS_COMPILE}strip" CFLAGS="$cflags" LDFLAGS="$ldflags";
mv -f loki_tool "$BUILD/$OUTPUT/loki_tool";
make $ARGS clean;
}

busybox() {
local curtag dir i j savedpath;
case $1 in
update)
cd android-busybox-ndk;
git checkout master >/dev/null 2>&1;
echo -n "--- android-busybox-ndk: ";
git pull origin;
cd ..;
cd busybox*;
git fetch --tags >/dev/null;
curtag=$(git describe --tags `git rev-list --tags --max-count=1`);
dir="busybox-${curtag//_/.}";
echo -n "--- busybox: ";
if [ "$dir" != "$(basename $PWD)" -o "$FORCE" ]; then
echo "Checking out $curtag";
git reset -- . >/dev/null;
git clean -df >/dev/null;
git checkout -- .;
git checkout -f $curtag 2>&1 | tail -n 1;
cd ..;
mv busybox* $dir;
else
echo "Already up to date.";
cd ..;
fi;
return;
;;
config)
echo "--- Configuring busybox";
cd busybox*;
[ "$HEADERS" ] && bbconfig=$HEADERS || bbconfig=unified;
cp -fv $AIKHOME/android-busybox-ndk/osm0sis-full-$bbconfig.config .config;
patches="$(head -n1 .config | grep -o 'patches .*$' | cut -c9- | sed -e 's/,//g' -e 's/*//g')";
[ ! "$patches" ] && patches=all;
for i in $patches; do
[ "$i" = "all" ] && unset i;
for j in $AIKHOME/android-busybox-ndk/patches/$i*.patch; do
echo $j; patch --forward -p1 < $j;
done;
done;
cd ..;
return;
;;
esac;

cd busybox*;
savedpath="$PATH";
export PATH="$(dirname $CROSS_COMPILE):$PATH";
if [ "$ARGS" = --silent ]; then
make $ARGS ARCH="$(basename $OUTPUT)" CROSS_COMPILE=$CROSS_COMPILE >/dev/null 2>&1;
else
make $ARGS ARCH="$(basename $OUTPUT)" CROSS_COMPILE=$CROSS_COMPILE;
fi;
mv -f busybox "$BUILD/$OUTPUT";
make $ARGS clean >/dev/null;
export PATH="$savedpath";
}

lz4() {
local curtag define dir flags ldflags savedcc;
case $1 in
update)
cd lz4*;
git fetch --tags >/dev/null;
curtag=$(git describe --tags `git rev-list --tags --max-count=1`);
dir="lz4-$(echo $curtag | cut -c 2-)";
echo -n "--- lz4: ";
if [ "$dir" != "$(basename $PWD)" -o "$FORCE" ]; then
echo "Checking out $curtag";
git reset -- . >/dev/null;
git clean -df >/dev/null;
git checkout -- .;
git checkout -f $curtag 2>&1 | tail -n 1;
cd ..;
mv lz4* $dir;
else
echo "Already up to date.";
fi;
return;
;;
config) return;;
esac;

cd lz4*/programs;
ldflags="-Wl,--gc-sections -s";
case $OUTPUT in
linux*) ;;
macos*) ldflags="-Wl,-dead_strip";;
*) flags=" -static"; define="-D__ANDROID_API__=21";;
esac;
savedcc="$CC"
export CC=$CROSS_COMPILE"$CC $ldflags -ffunction-sections $define"$flags;
if [ "$ARGS" = --silent ]; then
make $ARGS WINBASED=no lz4 >/dev/null 2>&1;
else
make VERBOSE=1 WINBASED=no lz4;
fi;
mv -f lz4 "$BUILD/$OUTPUT/lz4";
make $ARGS clean >/dev/null;
export CC="$savedcc";
}

xz() {
local cflags chain curtag dep dir i ldflags savedpath;
cd xz*;
case $1 in
update)
git fetch --tags >/dev/null;
curtag=$(git tag | grep -vE 'alpha|beta' | tail -n 1);
dir="xz-$(echo $curtag | cut -c 2-)";
echo -n "--- xz: ";
if [ "$dir" != "$(basename $PWD)" -o "$FORCE" ]; then
echo "Checking out $curtag";
git reset -- . >/dev/null;
git clean -df >/dev/null;
git checkout -- .;
git checkout -f $curtag 2>&1 | tail -n 1;
echo "building Autotools (configure) files...";
autoreconf -fi >/dev/null 2>&1;
cd ..;
mv xz* $dir;
else
echo "Already up to date.";
fi;
return;
;;
config)
echo "--- Configuring xz";
savedpath="$PATH";
ldflags="-static -Wl,--gc-sections";
cflags="-O3 -ffunction-sections -s -D__ANDROID_API__=21";
for i in arm-linux-androideabi i686-linux-android mipsel-linux-android aarch64-linux-android x86_64-linux-android mips64el-linux-android; do
echo -e "\nCreating configs for $i ...";
chain=$(echo $XTOOLS/$i*$HEADERS | rev | cut -d\ -f1 | rev);
export PATH="$chain/bin:$PATH";
./configure --host=$i --disable-shared --enable-static --with-sysroot=$chain/sysroot LD=$i-ld LDFLAGS="$ldflags" CFLAGS="$cflags" --disable-xzdec --disable-lzmadec --disable-lzmainfo --disable-lzma-links --disable-scripts;
sed -i "s;^sys_lib_search_path_spec=.*;sys_lib_search_path_spec=\'$chain/lib/gcc $chain/lib $chain/sysroot/usr/lib \';" config.status;
cp -f config.status config.$i;
export PATH="$savedpath";
done;
return;
;;
esac;

savedpath="$PATH";
export PATH="$(dirname $CROSS_COMPILE):$PATH";
ldflags="-all-static -Wl,--gc-sections";
cp -f config.$ARCH config.status;
if [ "$ARGS" = --silent ]; then
./config.status >/dev/null;
cd src;
make all LDFLAGS="$ldflags" >/dev/null;
else
./config.status;
cd src;
make all LDFLAGS="$ldflags";
fi;
mv -f xz/xz "$BUILD/$OUTPUT";
for dep in */.deps/*; do echo "# dummy" > $dep; done;
make $ARGS clean >/dev/null;
export PATH="$savedpath";
}

file() {
local cflags chain curtag dep dir i ldflags savedpath;
cd file*;
case $1 in
update)
git fetch --tags >/dev/null;
curtag=$(git describe --tags `git rev-list --tags --max-count=1`);
dir="file-$(echo ${curtag//_/.} | cut -c 5-)";
echo -n "--- file: ";
if [ "$dir" != "$(basename $PWD)" -o "$FORCE" ]; then
echo "Checking out $curtag";
git reset -- . >/dev/null;
git clean -df >/dev/null;
git checkout -- .;
git checkout -f $curtag 2>&1 | tail -n 1;
echo "building Autotools (configure) files...";
autoreconf -fi >/dev/null 2>&1;
cd ..;
mv file* $dir;
else
echo "Already up to date.";
fi;
return;
;;
config)
echo "--- Configuring file";
savedpath="$PATH";
ldflags="-static -Wl,--gc-sections";
cflags="-O3 -ffunction-sections -s -D__ANDROID_API__=21";
for i in arm-linux-androideabi i686-linux-android mipsel-linux-android aarch64-linux-android x86_64-linux-android mips64el-linux-android; do
echo -e "\nCreating configs for $i ...";
chain=$(echo $XTOOLS/$i*$HEADERS | rev | cut -d\ -f1 | rev);
export PATH="$chain/bin:$PATH";
./configure --host=$i --disable-shared --enable-static --with-sysroot=$chain/sysroot LD=$i-ld LDFLAGS="$ldflags" CFLAGS="$cflags";
sed -i "s;^sys_lib_search_path_spec=.*;sys_lib_search_path_spec=\'$chain/lib/gcc $chain/lib $chain/sysroot/usr/lib \';" config.status;
cp -f config.status config.$i;
export PATH="$savedpath";
done;
return;
;;
esac;

savedpath="$PATH";
export PATH="$(dirname $CROSS_COMPILE):$PATH";
ldflags="-all-static -Wl,--gc-sections";
cp -f config.$ARCH config.status;
if [ "$ARGS" = --silent ]; then
./config.status >/dev/null;
cd src;
make all LDFLAGS="$ldflags" >/dev/null;
else
./config.status;
cd src;
make all LDFLAGS="$ldflags";
fi;
mv -f file "$BUILD/$OUTPUT";
for dep in .deps/*; do echo "# dummy" > $dep; done;
make $ARGS clean >/dev/null;
export PATH="$savedpath";
}

magic() {
local i outfile;
cd file*/magic;
outfile=magic;
echo "#------------------------------------------------------------------------------" > $outfile;
echo "# Slimmed down magic file for archives only" >> $outfile;
cat Magdir/archive >> $outfile;
echo -ne "\n" >> $outfile;
head -n -1 Magdir/compress >> $outfile;
cat Magdir/android >> $outfile;
for i in XZ LZMA LZ4; do
sed -i "s;${i} compressed;${i,,} compressed;" $outfile;
done;
sed -i 's/0x184c2102\tlz4/0x184c2102\tlz4-l/' $outfile;
for i in byte-swapped ASCII; do
sed -i "s;${i} cpio;cpio ${i};g" $outfile;
done;
sed -i 's;^!:ext;#!:ext;g' $outfile;
sed -i '/# LHARC\/LHA archiver/,/^\s*$/d' $outfile;
sed -i '/rar-file-header/,/^\s*$/d' $outfile;
sed -i '/rar-archive-header/,/^\s*$/d' $outfile;
sed -i '/# RAR (Roshal Archive) archive/,/^\s*$/d' $outfile;
sed -i '/# xar (eXtensible ARchiver) archive/,/^\s*$/d' $outfile;
sed -i '/# PMA (CP\/M derivative of LHA)/,/^\s*$/d' $outfile;
sed -i '/# Zstandard Dictionary ID subroutine/,/^\s*$/d' $outfile;
sed -i '/# Zstandard compressed data/,/^\s*$/d' $outfile;
sed -i '/# Android Backup archive/,/^\s*$/d' $outfile;
sed -i '/# \*.pit files by Joerg Jenderek/,/^\s*$/d' $outfile;
sed -i '/PIT-entry/,/^\s*$/d' $outfile;
sed -i '/\tname\t/d' $outfile;
sed -i '/\tuse\t/d' $outfile;
sed -i '/\toffset\t/d' $outfile;
mv -f magic $BUILD;
}

clean() {
local dep i;
if [ ! "$NOCLEAN" ]; then
echo -e "\nCleaning ...";
rm -f file*/magic/magic futility/libcrypto*.a;
for i in mkbootimg pxa-mkbootimg elftool unpackelf mboot uboot* mkmtkhdr futility blobtools dhtbsign rkflashtool lokitool lz4*/programs xz*/src file*/src busybox*; do
if [ -e $AIKHOME/$i ]; then
cd $AIKHOME/$i;
for dep in */.deps/*; do
[ -e $dep ] && echo "# dummy" > $dep;
done;
for dep in .deps/*; do
[ -e $dep ] && echo "# dummy" > $dep;
done;
make clean >/dev/null 2>&1;
fi;
done;
fi;
}

cleanall() {
if [ ! "$NOCLEAN" ]; then
clean;
rm -rf $BUILD;
fi;
}

reset() {
local i;
cleanall;
cd $AIKHOME;
for i in arm-linux-androideabi i686-linux-android mipsel-linux-android aarch64-linux-android x86_64-linux-android mips64el-linux-android; do
rm -f xz*/config.$i file*/config.$i;
done;
find xz* file* -iname Makefile -exec rm -f {} + 2>/dev/null;
rm -rf busybox*/.config* busybox*/patches;
for i in 32 64; do
if [ -e busybox$i* ]; then
cd busybox$i*;
git reset -- .;
git clean -df;
git checkout -- .;
for i in $(find . | grep -E "c.rej|c.orig"); do
echo $i;
rm $i;
done;
cd ..;
fi;
done;
unset CC CROSS_COMPILE;
}

openssl() {
local i savedpath target triple;
cd $AIKHOME/openssl;
echo -e "\nBuilding NDK openssl prebuilt libraries ...";
make distclean; # may fail; here to ensure any failed previous build gets cleaned up
git checkout OpenSSL_1_1_1s;
export ANDROID_NDK_HOME=$AIKHOME/android-ndk-r15c; # use the full NDK since OpenSSL is nicely actually equipped for it
savedpath="$PATH";
for i in arm-linux-androideabi-4.9 x86-4.9 mipsel-linux-android-4.9 aarch64-linux-android-4.9 x86_64-4.9 mips64el-linux-android-4.9; do
triple=${i/-4.9/};
case $i in
aarch*) target=android-arm64;;
arm*) target=android-arm;;
x86_64*) target=android-x86_64; triple=x86_64-linux-android;;
x86*) target=android-x86; triple=i686-linux-android;;
mips64*) target=android-mips64;;
mips*) target=android-mips;;
esac;
export PATH=$ANDROID_NDK_HOME/toolchains/$i/prebuilt/linux-x86_64/bin:$PATH;
./Configure $target -D__ANDROID_API__=21 no-hw no-threads no-shared no-ssl2 no-zlib no-comp no-asm no-dso;
make build_libs;
export PATH="$savedpath";
rm -rf $AIKHOME/libcrypto/${triple}-prebuilt;
mkdir -p $AIKHOME/libcrypto/${triple}-prebuilt;
mv -fv libcrypto.a libssl.a $AIKHOME/libcrypto/${triple}-prebuilt;
cp -afr include $AIKHOME/libcrypto/${triple}-prebuilt;
make distclean;
done;
unset ANDROID_NDK_HOME;
}

init() {
local i;
cd $AIKHOME;
echo -e "\nRemoving repos ...";
rm -rf mkbootimg pxa-mkbootimg elftool unpackelf mboot uboot* futility openssl mkmtkhdr blobtools dhtbsign rkflashtool lokitool lz4* xz* file* busybox* android-busybox-ndk bootimg-info;
echo -e "\nCreating repos ...";
for i in mkbootimg pxa-mkbootimg elftool unpackelf mboot mkmtkhdr dhtbsign futility bootimg-info; do
echo "--- Initializing $i";
git clone https://github.com/osm0sis/$i;
done;
echo "--- Initializing uboot";
git clone https://source.denx.de/u-boot/u-boot.git uboot;
echo "--- Initializing openssl (for futility and uboot)";
git clone -b OpenSSL_1_1_1-stable git://git.openssl.org/openssl.git;
echo "--- Initializing blobtools";
git clone https://github.com/AndroidRoot/BlobTools blobtools;
echo "--- Initializing rkflashtool";
git clone https://github.com/linux-rockchip/rkflashtool rkflashtool;
echo "--- Initializing lokitool";
git clone https://github.com/djrbliss/loki lokitool;
echo "--- Initializing busybox (and android patches)";
git clone git://busybox.net/busybox busybox;
git clone https://github.com/osm0sis/android-busybox-ndk;
echo "--- Initializing lz4";
git clone https://github.com/lz4/lz4;
echo "--- Initializing file";
git clone https://github.com/file/file;
echo "--- Initializing xz (silent)";
git clone -b v5.2 https://git.tukaani.org/xz.git;
ACTION="update ";
main $ACTION;
openssl;
}

main() {
local common genericlist i j k queue savedpath toolchain;
case $1 in
update) cleanall; echo -e "\nUpdating repos ...";;
*) clean;;
esac;
[ "$TARGETLIST" ] || TARGETLIST="mobile/arm mobile/x86 mobile/mips mobile/arm64 mobile/x86_64 mobile/mips64 linux/i686 linux/x86_64 macos/i386 macos/x86_64";
for OUTPUT in $TARGETLIST; do
genericlist="mkbootimg/unpackbootimg pxa-mkbootimg/pxa-unpackbootimg elftool unpackelf mboot mkmtkhdr dhtbsign bootimg-info";
common="mkbootimg/unpackbootimg pxa-mkbootimg/pxa-unpackbootimg elftool unpackelf mboot mkimage/dumpimage mkmtkhdr futility blobpack/blobunpack dhtbsign rkcrc lokitool lz4 bootimg-info";
queue="$common busybox xz file";
case $1 in
update|config) ;;
*)
case $OUTPUT in
*arm) ARCH=arm-linux-androideabi;;
*x86) ARCH=i686-linux-android;;
*mips) ARCH=mipsel-linux-android;;
*arm64) ARCH=aarch64-linux-android;;
mobile/x86_64) ARCH=x86_64-linux-android;;
*mips64) ARCH=mips64el-linux-android;;
linux/i686) ARCH=i686-linux-gnu; queue="$common";;
linux/x86_64) ARCH=x86_64-linux-gnu; queue="$common";;
macos/i386) ARCH=i386-apple-darwin11; queue="$common";;
macos/x86_64) ARCH=x86_64-apple-darwin11; queue="$common";;
*) echo -e "\naik-build: invalid target -- '$OUTPUT'\n accepted targets -- mobile/arm mobile/x86 mobile/mips mobile/arm64 mobile/x86_64 mobile/mips64 linux/i686 linux/x86_64 macos/i386 macos/x86_64"; continue;;
esac;
case $OUTPUT in
linux*) export CC=gcc; unset CROSS_COMPILE; toolchain=$ARCH;;
macos*) export CC=clang; export CROSS_COMPILE=$OSXCROSS/target/bin/$ARCH-; savedpath="$PATH"; export PATH="$(dirname $CROSS_COMPILE):$PATH"; toolchain=$ARCH;;
*) export CC=gcc; export CROSS_COMPILE=$(echo $XTOOLS/$ARCH*$HEADERS | rev | cut -d\ -f1 | rev)/bin/$ARCH-; toolchain=$(basename "$(dirname "$(dirname $CROSS_COMPILE)")");;
esac;
[ "$OUTPUT" = "linux/i686" ] && export CC="gcc -m32 -mtune=i686";
echo -e "\nBuilding for $OUTPUT...";
echo "Toolchain: $toolchain";
mkdir -p "$BUILD/$OUTPUT";
;;
esac;
for i in $queue; do
case $i in
*/*) j=$(echo $i | cut -d/ -f1); k=$(echo $i | cut -d/ -f2);;
*) j=$i; k=dummy;;
esac;
if [ ! "$ONLY" ]; then
case " $SKIP " in
*" $j "*|*" $k "*) echo "*** Skipping $i";;
*)
case $1 in
update|config) ;;
*) echo "--- $ACTION$i";;
esac;
cd $AIKHOME;
case $genericlist in
*$i*) generic $i $1;;
*) $i $1;;
esac;
;;
esac;
else
case " $ONLY " in
*" $j "*|*" $k "*)
case $1 in
update|config) ;;
*) echo "--- $ACTION$i";;
esac;
cd $AIKHOME;
case $genericlist in
*$i*) generic $i $1;;
*) $i $1;;
esac;
;;
*) echo "*** Skipping $i";;
esac;
fi;
done;
case $1 in
update|config) return;;
*) [ "$savedpath" ] && export PATH="$savedpath"; unset CC CROSS_COMPILE;;
esac;
done;
echo -e "\nBuilding common ...";
if [ ! "$ONLY" ]; then
case $SKIP in
*magic*) echo "*** Skipping slimmed magic";;
*)
echo "--- Compiling slimmed magic";
cd $AIKHOME;
magic;
;;
esac;
else
case $ONLY in
*magic*)
echo "--- Compiling slimmed magic";
cd $AIKHOME;
magic;
;;
*) echo "*** Skipping slimmed magic";;
esac;
fi;
echo -e "\nDone!";
}

cd $AIKHOME;
ARGS=--silent;
until [ ! "$1" ]; do
case $1 in
verbose) unset ARGS;;
noclean) NOCLEAN=1;;
force) FORCE=1;;
headers) HEADERS=$2; shift;;
targets) TARGETLIST=$2; shift;;
update|config) ACTION="$1 ";;
only|skip) FILTER=$1; declare ${FILTER^^}="$2"; shift;;
clean*|reset|init|openssl) $1; exit 0;;
help) echo "aik-build.sh clean, cleanall, reset, init, [force] update, config, verbose, noclean, headers <suffix>, targets \"<list>\", only \"<list>\", skip \"<list>\", or without args"; exit 1;;
*) echo "aik-build: invalid option -- '$*'"; exit 1;;
esac;
shift;
done;
main $ACTION;
exit 0;

I'm also abusing the way the external sources' Makefiles work in order to insert Modding.MyMind/SHM's optimized/stripped flags, so that's kinda fun too. Thanks to his excellent work on achieving true static compiles for file/xz as well.

For completion, my hacky build/packaging scripts for AIK and all my Diffusion Installer module zips, and the (deprecated) stripped-down Linux aik-build I used to build only NDK compiles of mkimage/dumpimage are available here: https://xdaforums.com/showpost.php?p=56343410&postcount=290

Lastly, here's a regression tester I wrote which will run on Cygwin, Android, Linux and macOS ;): https://xdaforums.com/showpost.php?p=42071707&postcount=32

Changelog:

Edit

: Added initializing everything from scratch by automatically pulling the git repos, and updating them to their latest tagged releases. :good:

Edit 2

: Added Linux x86_64 support.

Edit 3

: Added Android x64 support, and Linux mkbootfs building. :D

Edit 4

: Added busybox building. :victory:

Edit 5

: Updated for ELF, MTK and Loki utilities, added skip feature and help. :cyclops:

Edit 6

: Updated for futility support, removed workaround for x86 + MIPS busybox compiles, made skip accept either mkbootimg or unpackbootimg, added only and noclean features. :cool:

Edit 7

: Refactored config and update code so each binary has a self-contained function with update, config and build, allowing extension of skip and only to config and update. :cowboy:

Edit 8

: Rewrote skip/only feature more elegantly to allow scaling to additional multi-tool ("/") names, added blobtools building, rewrote lokitool building to use the official repo, latest file update workaround.

Edit 9

: Removed file + blobtools workarounds, added u-boot tools (broken builds in Windows) and pxa board variant bootimg tools building.

Edit 10

: Pull in the required busybox patches from the .config on-the-fly, use my updated libcrypto_static repo instead of mini-openssl, added rkcrc and dhtbsign building.

Edit 11

: Kill mkbootfs with fire :mad:;), and add macOS (Darwin) + clang support. :laugh:

Edit 12

: Add elftool, and link the other AIK build/packaging scripts.

Edit 13

: Update for Unified Header build changes, add choosing specific build targets, add selecting toolchain by suffix.

Edit 14

: Add mboot, update u-boot tools hacks, and use a generic build script for the simpler utilities (*bootimg, elftool, unpackelf, mboot, dhtbsign, mkmtkhdr).

Edit 15

: Update lz4 and slimmed magic file hacks, fix cleaning elftool.

Edit 16

: Major clean up, update u-boot tools hacks.

Edit 17

: Work around the latest u-boot bull****, magic and other fixes, add bootimg-info.

Edit 18

: Partial rewrites for WSL2 🎉 and latest osxcross, fix generic+futility CFLAGS handling, update u-boot build hacks, deprecate libcrypto_static, switch to openssl 1.1.1x (since u-boot now requires it) and build it in-line as a pre-req in init.