#!/usr/bin/env bash 
set -e
set -x

# point to make
MAKE_4x=/usr/local/bin/make

skarnet_packages=(
skalibs
execline
s6
s6-portable-utils
s6-linux-utils
s6-dns
s6-networking
)

# software versions
declare -A versions
versions[make]=4.1
versions[linux]=3.18.5
versions[musl]=1.0.4
versions[skalibs]=2.3.1.0
versions[execline]=2.1.0.0
versions[s6]=2.1.1.2
versions[s6-portable-utils]=2.0.0.1
versions[s6-linux-utils]=2.0.1.0
versions[s6-dns]=2.0.0.2
versions[s6-networking]=2.1.0.0

declare -A includes
includes[skalibs]="--with-include=/usr/musl/include"
includes[execline]="--with-include=/opt/skalibs/usr/include ${includes[skalibs]}"
includes[s6]="--with-include=/opt/execline/usr/include ${includes[execline]}"
includes[s6-portable-utils]="${includes[s6]}"
includes[s6-linux-utils]="--with-include=/opt/linux-headers/include ${includes[s6]}"
includes[s6-dns]="${includes[s6]}"
includes[s6-networking]="--with-include=/opt/s6-dns/usr/include --with-include=/opt/s6/usr/include ${includes[s6]}"

declare -A libs
libs[skalibs]="--with-lib=/usr/musl/lib"
libs[execline]="--with-lib=/opt/skalibs/usr/lib ${libs[skalibs]}"
libs[s6]="--with-lib=/opt/execline/usr/lib ${libs[execline]}"
libs[s6-portable-utils]="${libs[s6]}"
libs[s6-linux-utils]="${libs[s6]}"
libs[s6-dns]="${libs[s6]}"
libs[s6-networking]="--with-lib=/opt/s6-dns/usr/lib --with-lib=/opt/s6/usr/lib ${libs[s6]}"

declare -A sysdeps
sysdeps[skalibs]=""
sysdeps[execline]="--with-sysdeps=/opt/skalibs/usr/lib/skalibs/sysdeps"
sysdeps[s6]="${sysdeps[execline]}"
sysdeps[s6-portable-utils]="${sysdeps[execline]}"
sysdeps[s6-linux-utils]="${sysdeps[execline]}"
sysdeps[s6-dns]="${sysdeps[execline]}"
sysdeps[s6-networking]="${sysdeps[execline]}"

declare -A configopts
configopts[skalibs]="--datadir=/etc --enable-force-devr"
configopts[execline]=""
configopts[s6]=""
configopts[s6-portable-utils]=""
configopts[s6-dns]=""
configopts[s6-networking]=""

build_install_skarnet_package() {
    local package=$1
    cd /build
    curl -R -L -O "http://skarnet.org/software/${package}/${package}-${versions[$package]}.tar.gz"
    tar xf "${package}-${versions[$package]}.tar.gz"
    cd "${package}-${versions[$package]}"
    CC="musl-gcc" ./configure \
      --prefix=/usr \
      --libdir=/usr/lib \
      --enable-static \
      --disable-shared \
      --enable-static-libc \
      ${includes[$package]} \
      ${libs[$package]} \
      ${sysdeps[$package]} \
      ${configopts[$package]}
    ${MAKE_4x}
    ${MAKE_4x} DESTDIR="/opt/${package}" install
}

tar_skarnet_package() {
    local package=$1
    if [[ -d "/opt/${package}/usr/bin" ]]; then
        find "/opt/${package}/usr/bin" -type f -exec strip {} \;
    fi

    tar -czf "/dist/${package}-${versions[$package]}-linux-amd64-bin.tar.gz" \
      --exclude "usr/lib" \
      --exclude "usr/include" \
      -C "/opt/${package}" .

    local dev_dirs=""
    if [[ -d "/opt/${package}/usr/lib" ]]; then
        dev_dirs="usr/lib"
    fi
    if [[ -d "/opt/${package}/usr/include" ]]; then
        dev_dirs="${dev_dirs} usr/include"
    fi
    if [[ -n "${dev_dirs}" ]]; then
        tar -czf "/dist/${package}-${versions[$package]}-linux-amd64-dev.tar.gz" \
        -C "/opt/${package}" $dev_dirs
    fi
}

# create build dir
mkdir -p /build /dist

# install make
cd /build
curl -R -L -O http://ftp.gnu.org/gnu/make/make-${versions[make]}.tar.gz
tar xf make-${versions[make]}.tar.gz
cd make-${versions[make]}

./configure
make
make install

# install musl
cd /build
curl -R -L -O http://www.musl-libc.org/releases/musl-${versions[musl]}.tar.gz
tar xf musl-${versions[musl]}.tar.gz
cd musl-${versions[musl]}

CFLAGS="-fno-toplevel-reorder -fno-stack-protector" \
  ./configure                                       \
    --prefix=/usr/musl                              \
    --exec-prefix=/usr                              \
    --disable-shared
${MAKE_4x}
${MAKE_4x} install

# install linux-headers
cd /build
curl -R -L -O http://www.kernel.org/pub/linux/kernel/v3.x/linux-${versions[linux]}.tar.xz
tar xf linux-${versions[linux]}.tar.xz
cd linux-${versions[linux]}
for i in /patches/linux/*.patch; do
    patch -p1 -i "${i}" || true
done
make headers_install ARCH="$(uname -m)" INSTALL_HDR_PATH="/opt/linux-headers" CC="musl-gcc"

# install skarnet packages
for package in "${skarnet_packages[@]}"; do
    build_install_skarnet_package ${package}
    tar_skarnet_package ${package}
done

# generate release.md
echo "Built using \`make-${versions[make]}\`, \`musl-${versions[musl]}\` and \`linux-headers-${versions[linux]}\`" >> /dist/release.md
echo "" >> /dist/release.md
echo "| Software | Version |" >> /dist/release.md
echo "| -------- |:-------:|" >> /dist/release.md
for package in "${skarnet_packages[@]}"
do
  echo "| ${package} | ${versions[${package}]} |" >> /dist/release.md
done

# generate manifest.txt
for package in "${skarnet_packages[@]}"
do
  echo "${package}=${versions[${package}]}" >> /dist/manifest.txt
done
echo "" >> /dist/manifest.txt