#!/usr/bin/env bash
#
# build the Linux artifacts for amd64, arm, arm64
#
# runs one background job per desired architecture unless there are too few CPUs
#
# 

set -o pipefail -e -u

# if no architectures supplied then default list of three
if (( ${#} )); then
    typeset -a JOBS=(${@})
else
    typeset -a JOBS=(amd64 arm arm64)
fi

# specify the Go template used by Gox to save the artifacts
GOX_OUTPUT="dist/{{.Arch}}/{{.OS}}/{{.Dir}}"
# count the number of available CPUs for time-efficient parallelism
PROC_COUNT=$(nproc --all)
# compute the number of processors available for each job, rounded down to integer
PROCS_PER_JOB=$((PROC_COUNT / ${#JOBS[@]}))
# if multiple jobs and at least one processor for each job then background, else foreground with all available CPUs-1 (gox default)
if (( ${#JOBS[@]} > 1 && ${PROCS_PER_JOB} )); then 
    BACKGROUND="&"
    # initialize an associative array in which to map background PIDs to the ARCH being built
    typeset -A BUILDS
else
    BACKGROUND=""   # run normally in foreground
    PROCS_PER_JOB=0 # invokes gox default to use all CPUs-1
fi

for ARCH in ${JOBS[@]}; do
    GOX_CMD="
        gox \
            -cgo \
            -os=linux \
            -arch=${ARCH} \
            -output=${GOX_OUTPUT} \
            -parallel=${PROCS_PER_JOB} \
            ./cmd/zrok
    "
case ${ARCH} in
        amd64)  eval ${GOX_CMD} ${BACKGROUND}
                (( ${PROCS_PER_JOB} )) && BUILDS[${!}]=${ARCH}  # if greater than zero procs per job then map background pid->arch
        ;;
        arm)    eval CC=arm-linux-gnueabihf-gcc ${GOX_CMD} ${BACKGROUND}
                (( ${PROCS_PER_JOB} )) && BUILDS[${!}]=${ARCH}
        ;;
        arm64)  eval CC=aarch64-linux-gnu-gcc ${GOX_CMD} ${BACKGROUND}
                (( ${PROCS_PER_JOB} )) && BUILDS[${!}]=${ARCH}
        ;;
        *)      echo "ERROR: invalid architecture '${ARCH}', must be one of amd64, arm, arm64" >&2
                exit 1
        ;;
    esac
done

# if not background in parallel then exit now with well earned success
[[ -z "${BACKGROUND:-}" ]] && exit 0

# Wait for builds in the background and exit with an error if any fail
EXIT=0
while true; do
    # "wait -p" requires BASH >=5.1 which is present in Ubuntu 20.10 and Debian Bullseye
    wait -n -p JOB_PID; JOB_RESULT=$?
    echo "Building for ${BUILDS[$JOB_PID]} finished with result ${JOB_RESULT}"
    (( ${JOB_RESULT} )) && EXIT=1
done

exit ${EXIT}
