require 'package'

class Zstd_static < Package
  description 'Zstandard - Fast real-time compression algorithm'
  homepage 'https://facebook.github.io/zstd/'
  version '1.5.7-1'
  license 'BSD or GPL-2'
  compatibility 'all'
  source_url 'SKIP'
  binary_compression 'tar.xz'

  binary_sha256({
    aarch64: '3656581e4d8ab2cd9fd49d5b280139092bf6ec44970715142dc7a44af320f4b2',
     armv7l: '3656581e4d8ab2cd9fd49d5b280139092bf6ec44970715142dc7a44af320f4b2',
       i686: '9caa7aa0ce6b7b71165cc0b16d82ad83b9e609311225b381b574cd92acf18ae9',
     x86_64: '5f108a937cc27bb1ff05e7bc05bdb9e3eceb91204d76880f96103acdaa29a884'
  })

  conflicts_ok
  no_source_build
  no_zstd

  case ARCH
  when 'i686'
    @cross = 'i686-linux-musl'
  when 'x86_64'
    @cross = 'x86_64-linux-musl'
  when 'aarch64', 'armv7l'
    @cross = 'arm-linux-musleabihf'
  end

  def self.build
    File.write 'crew-static-builder.sh', <<~'BUILDER_EOF'
      #!/bin/bash
      # From https://gist.github.com/ryancdotorg/84275935f0b82578d8c222e2e915fc78
      # built binaries at https://ryanc-musl-bins.s3.amazonaws.com/SHA256SUMS.html

      set -eo pipefail
      set -x

      export BUILD_SCRIPT_DATE="$(date -r "$0" -Iseconds)"

      PV_VERSION=1.8.5
      SOCAT_VERSION=1.8.0.0
      NCURSES_VERSION=6.4
      READLINE_VERSION=8.2
      OPENSSL_VERSION=1.1.1w
      LIBPCAP_VERSION=1.10.4
      ZLIB_VERSION=1.3.1
      TCPDUMP_VERSION=4.99.4
      RSYNC_VERSION=3.3.0
      XZ_VERSION=5.8.1
      LZ4_VERSION=v1.10.0
      ZSTD_VERSION=v1.5.7
      XXHASH_VERSION=v0.8.2
      DROPBEAR_VERSION=2022.83
      GPGERROR_VERSION=1.48
      GCRYPT_VERSION=1.10.2
      GLIB_VERSION=2.80.0
      CARES_VERSION=1.28.1
      PCRE_VERSION=8.45
      WIRESHARK_VERSION=4.0.11
      LIBSODIUM_VERSION=1.0.19-RELEASE
      MINISIGN_VERSION=v0.11-ryanc.4
      SHA2SUM_VERSION=v0.3.1
      MULTICALL_VERSION=v0.0.6

      BASE_DIR=`pwd`
      SOURCE_DIR="$BASE_DIR/source"
      BUILD_DIR="$BASE_DIR/build"
      SCRIPT_DIR="`pwd`"
      OUTPUT_DIR="$SCRIPT_DIR/output"

      ORIG_PATH=$PATH

      function setcross() {
          MUSL_CROSS=${1:-armv7l-linux-musleabihf}
          CROSS_BIN="$BUILD_DIR/$MUSL_CROSS-cross/bin"
          CROSS_PFX="$CROSS_BIN/$MUSL_CROSS"
          BIN_DIR="$OUTPUT_DIR/$MUSL_CROSS"
          mkdir -p $BIN_DIR

          if command -v _ccache > /dev/null; then
              export CC="ccache $CROSS_PFX-gcc"
              export CXX="ccache $CROSS_PFX-g++"
          else
              export CC=$CROSS_PFX-gcc
              export CXX=$CROSS_PFX-g++
          fi

          export AR=$CROSS_PFX-ar
          export AS=$CROSS_PFX-as
          export LD=$CROSS_PFX-ld
          export RANLIB=$CROSS_PFX-ranlib

          export PATH=$CROSS_BIN:$ORIG_PATH
          export STRIP="$CROSS_PFX-strip -s -R .comment -R .hash -R .gnu.hash"
          export LDFLAGS="-flto -Wl,--gc-sections"
          export CFLAGS="-flto -fno-inline-small-functions -ffunction-sections -fdata-sections -Wl,--gc-sections -static -Os"
          export CXXFLAGS="$CFLAGS"
          export MAKEFLAGS="-sj$((`grep -c '^processor' /proc/cpuinfo` * 125 / 100))"
      }

      function setnative() {
          MUSL_CROSS=${1:-armv7l-linux-musleabihf}
          CROSS_BIN="$BUILD_DIR/$MUSL_CROSS-native/bin"
          # CROSS_PFX="$CROSS_BIN/$MUSL_CROSS"
          CROSS_PFX="$CROSS_BIN/"
          BIN_DIR="$OUTPUT_DIR/$MUSL_CROSS"
          mkdir -p $BIN_DIR

          if command -v _ccache > /dev/null; then
              export CC="ccache gcc"
              export CXX="ccache g++"
          else
              export CC=${CROSS_PFX}gcc
              export CXX=${CROSS_PFX}g++
          fi

          export AR=${CROSS_PFX}ar
          export AS=${CROSS_PFX}as
          export LD=${CROSS_PFX}ld
          export RANLIB=${CROSS_PFX}ranlib

          export PATH=$CROSS_BIN:$ORIG_PATH
          export STRIP="strip -s -R .comment -R .hash -R .gnu.hash"
          export LDFLAGS="-flto -Wl,--gc-sections"
          export CFLAGS="-flto -fno-inline-small-functions -ffunction-sections -fdata-sections -Wl,--gc-sections -static -Os"
          export CXXFLAGS="$CFLAGS"
          export MAKEFLAGS="-sj$((`grep -c '^processor' /proc/cpuinfo` * 125 / 100))"
      }

      function extract() {
          PACKAGE="$1"
          BASEURL="$2"
          FILEEXT="$3"
          VERSION="${4:-}"

          export PS4="+$arch:$PACKAGE+ "

          # Clean/Download/Extract
          mkdir -p "$BUILD_DIR"
          cd "$BUILD_DIR"

          if [ "$FILEEXT" = "git" ]; then
              if [ -d "$PACKAGE" ]; then
                  cd "$PACKAGE"
                  git clean -fdx
                  git reset --hard HEAD
                  if [[ ! -z "$VERSION" ]]; then
                      git checkout "$VERSION" \
                      || git fetch --depth 1 origin tag "$VERSION" --no-tags \
                      && git checkout "$VERSION"
                  else
                      git pull
                  fi
              else
                  if [[ ! -z "$VERSION" ]]; then
                      git clone --depth 1 --branch "$VERSION" "$BASEURL/$PACKAGE.$FILEEXT"
                  else
                      git clone --depth 1 "$BASEURL/$PACKAGE.$FILEEXT"
                  fi
                  cd "$PACKAGE"
              fi
              printf '%s  %s.git\n' $(git rev-parse HEAD) "$PACKAGE" >> "$BUILD_DIR/hashes"
          else
              if [ -d "$PACKAGE-$VERSION" ]; then rm -rf "$PACKAGE-$VERSION"; fi
              if ! tar -xaf "$PACKAGE-$VERSION.$FILEEXT" > /dev/null 2> /dev/null; then
                  curl -LO "$BASEURL/$PACKAGE-$VERSION.$FILEEXT"
                  if [ -d "$PACKAGE-$VERSION" ]; then rm -rf "$PACKAGE-$VERSION"; fi
                  tar -xaf "$PACKAGE-$VERSION.$FILEEXT"
              fi
              ln -fs "$PACKAGE-$VERSION" "$PACKAGE"
              sha256sum "$PACKAGE-$VERSION.$FILEEXT" >> "$BUILD_DIR/hashes"
              cd "$PACKAGE-$VERSION"
          fi

          # Patch
          if [ -d "$BUILD_DIR/patches" ]; then
              for f in "$BUILD_DIR/patches/$PACKAGE"-*.diff; do
                  [ -e "$f" ] || continue
                  patch -p1 < "$f"
              done
              for f in "$BUILD_DIR/patches/$PACKAGE"-*.sh; do
                  [ -e "$f" ] || continue
                  "$f"
              done
          fi
      }

      function output() {
          BIN="$1"
          DST="${2:-}"
          mkdir -p "$BIN_DIR"
          chmod 755 "$BIN"
          $STRIP "$BIN"
          cp "$BIN" "$BIN_DIR/$DST"
      }

      function get_musl() {
          cd "$BUILD_DIR"

          HASHES="musl.SHA512SUMS"
          FLAGS="-L -o $HASHES"
          if [ -e "$HASHES" ]; then
              FLAGS="$FLAGS -z $HASHES"
          fi
          curl $FLAGS https://musl.cc/SHA512SUMS

          if [ ! -e "$MUSL_CROSS-native.tgz" ]; then
              if [ -d "$MUSL_CROSS-native" ]; then
                 rm -rf "$MUSL_CROSS-native"
              fi
              curl -LO "https://musl.cc/$MUSL_CROSS-native.tgz"
          fi

          if (fgrep "$MUSL_CROSS-native.tgz" "$HASHES" | sha512sum --strict --warn --status -c -); then
              if [ ! -d "$MUSL_CROSS-native" ]; then
                  tar -xzf "$MUSL_CROSS-native.tgz"
              fi
          else
              rm "$MUSL_CROSS-native.tgz"
              get_musl
          fi
      }

      function build_pv() {
          # Download/extract
          extract pv https://www.ivarch.com/programs/sources tar.gz $PV_VERSION

          # Configure
          ./configure \
              --enable-static \
              --disable-nls \
              --disable-dependency-tracking

          # Build
          make
          output pv
          echo "** Finished building pv"
      }

      function build_openssl() {
          # Download/extract
          extract openssl https://www.openssl.org/source tar.gz $OPENSSL_VERSION

          TARGET="$1"
          if [ -z "$TARGET" ]; then
              case $MUSL_CROSS in
                  x86_64-linux-musl)
                  TARGET=linux-x86_64
                  ;;
                  aarch64-linux-musl)
                  TARGET=linux-aarch64
                  ;;
                  armv*-linux-*)
                  TARGET=linux-armv4
                  ;;
                  mips-linux-*)
                  TARGET=linux-mips32
                  ;;
                  mipsel-linux-*)
                  TARGET=linux-mips32
                  ;;
                  *)
                  TARGET=linux-generic32
                  ;;
              esac
          fi

          # Configure
          SOURCE_DATE_EPOCH="$(date -r CHANGES '+%s')" \
          ./Configure \
              --openssldir=/etc/ssl \
              no-shared no-async no-threads no-err no-hw no-engine no-dso \
              no-static-engine no-capieng no-comp \
              no-tests no-unit-test \
              no-ts no-cms \
              no-rfc3779 \
              no-srtp \
              no-ssl-trace no-ct no-multiblock \
              no-cmac no-blake2 no-asm \
              no-siphash \
              no-scrypt no-ocb no-egd \
              no-md4 no-whirlpool no-rmd160 \
              no-des no-bf no-rc2 no-rc4 no-rc5 \
              no-sm2 no-sm3 no-sm4 \
              no-gost no-idea no-cast no-seed no-camellia no-aria \
              no-chacha no-poly1305 \
              no-dh no-dsa no-psk no-srp \
              no-ec2m \
              no-weak-ssl-ciphers \
              no-dgram no-sctp \
              no-dtls no-ssl2 no-ssl3 no-tls1 no-tls1_1 \
              no-ssl3-method no-tls1-method no-tls1_1-method \
              no-dtls1-method no-dtls1_2-method \
              no-crypto-mdebug \
              $TARGET

          # Build
          SOURCE_DATE_EPOCH="$(date -r CHANGES '+%s')" \
          make
          output apps/openssl
          echo "** Finished building OpenSSL"
      }

      function build_gpgerror(){
          # Download/extract
          extract libgpg-error https://www.gnupg.org/ftp/gcrypt/libgpg-error tar.gz $GPGERROR_VERSION

          # Configure
          ./configure \
              --enable-silent-rules \
              --disable-languages \
              --disable-doc \
              --disable-tests \
              --disable-nls \
              --disable-dependency-tracking \
              --enable-static --disable-shared \
              --prefix="$BUILD_DIR/install" \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make install
          # no idea why this needs to be done...
          mkdir -p "$BUILD_DIR/install/bin"
          cp src/gpg-error-config "$BUILD_DIR/install/bin/"
          echo "** Finished building libgpg-error"
      }

      function build_gcrypt(){
          # Download/extract
          extract libgcrypt https://www.gnupg.org/ftp/gcrypt/libgcrypt tar.gz $GCRYPT_VERSION

          # Configure
          ./configure \
              --enable-silent-rules \
              --disable-doc \
              --disable-dependency-tracking \
              --enable-static --disable-shared \
              --enable-ciphers="aes chacha20" \
              --enable-pubkey-ciphers="ecc rsa" \
              --enable-digests="sha256 sha512" \
              --enable-kdfs="pkdf2" \
              --with-libgpg-error-prefix="$BUILD_DIR/install" \
              --prefix="$BUILD_DIR/install" \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Disable tests
          sed -Ei 's/(SUBDIRS\s*=.*)\s+tests(\s+.+)?/\1\2/' Makefile*

          # Build
          make install
          echo "** Finished building libgcrypt"
      }

      function build_cares(){
          # Download/extract
          extract c-ares https://c-ares.org/download tar.gz $CARES_VERSION

          # Configure
          ./configure \
              --prefix="$BUILD_DIR/install" \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make install
          echo "** Finished building c-ares"
      }

      function build_pcre(){
          # Download/extract
          extract pcre https://downloads.sourceforge.net/project/pcre/pcre/$PCRE_VERSION tar.gz $PCRE_VERSION

          # Configure
          ./configure \
              --prefix="$BUILD_DIR/install" \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make install
          echo "** Finished building pcre"
      }

      function build_glib(){
          # https://download.gnome.org/sources/glib/2.74/glib-2.74.5.tar.xz
          # Download/extract
          extract glib https://download.gnome.org/sources/glib/$(echo $GLIB_VERSION | cut -d . -f 1-2) tar.xz $GLIB_VERSION

          MESON_CROSS_FILE="cross_$MUSL_CROSS.txt"
          MESON_CROSS_OS=linux
          MESON_CROSS_ENDIAN=little
          MESON_CROSS_CPU=$(echo "$MUSL_CROSS" | cut -d - -f 1)
          case $MUSL_CROSS in
              x86_64-linux-musl)
              MESON_CROSS_FAMILY=x86_64
              #MESON_CROSS_WRAPPER=qemu-x86_64-static
              ;;
              aarch64-linux-musl)
              MESON_CROSS_FAMILY=aarch64
              MESON_CROSS_WRAPPER=qemu-aarch64-static
              ;;
              armv*-linux-musl*)
              MESON_CROSS_FAMILY=arm
              MESON_CROSS_WRAPPER=qemu-arm-static
              ;;
              mips-linux-musl*)
              MESON_CROSS_ENDIAN=big
              MESON_CROSS_FAMILY=mips
              MESON_CROSS_WRAPPER=qemu-mips-static
              ;;
              mipsel-linux-musl*)
              MESON_CROSS_FAMILY=mipsel
              MESON_CROSS_WRAPPER=qemu-mipsel-static
              ;;
              *)
              MESON_CROSS_FAMILY=unknown
              ;;
          esac

          cat > "$MESON_CROSS_FILE" <<EoF
      [binaries]
      c = '$CROSS_PFX-gcc'
      cpp = '$CROSS_PFX-g++'
      ar = '$CROSS_PFX-ar'
      as = '$CROSS_PFX-as'
      ld = '$CROSS_PFX-ld'
      strip = '$CROSS_PFX-strip'

      [host_machine]
      system = '$MESON_CROSS_OS'
      cpu_family = '$MESON_CROSS_FAMILY'
      cpu = '$MESON_CROSS_CPU'
      endian = '$MESON_CROSS_ENDIAN'
      ${MESON_CROSS_WRAPPER+exe_wrapper = "'$MESON_CROSS_WRAPPER'"}
      EoF

          # XXX this is probably a terrible idea...
          if [ "$MESON_CROSS_FAMILY" = "x86_64" ]; then
              # insert lines overriding check
              sed -i '0,/^if not gl_cv_func_frexpl_works and/s//gl_cv_func_frexpl_broken_beyond_repair = false\n&/' glib/gnulib/meson.build
          fi

          # Configure
          CFLAGS="" CPPFLAGS="" LDFLAGS="" \
          meson setup \
              --prefix "$BUILD_DIR/install" \
              --buildtype minsize \
              --prefer-static \
              --default-library static \
              --cross-file "$MESON_CROSS_FILE" \
              -Dtests=false \
              "build_$MUSL_CROSS"

          # Build
          pushd "build_$MUSL_CROSS"
          meson compile
          meson install
          popd
          echo "** Finished building glib"
      }

      function build_wireshark(){
          # Download/extract
          extract wireshark https://www.wireshark.org/download/src/all-versions tar.xz $WIRESHARK_VERSION


          # Configure
          #sed -Ei \
          #    "s!/opt/local/lib!$BUILD_DIR/glib-$GLIB_VERSION/build_$MUSL_CROSS/install/usr/local/lib!" \
          #    cmake/modules/Find{GLIB2,GMODULE2,GTHREAD2}.cmake
          mkdir build
          pushd build
          PKG_CONFIG_LIBDIR="$BUILD_DIR/install/lib/pkgconfig" \
          CMAKE_PREFIX_PATH="$BUILD_DIR/install" \
          CFLAGS="-I$BUILD_DIR/install/include $CFLAGS" \
          CPPFLAGS="-I$BUILD_DIR/install/include $CPPFLAGS" \
          LDFLAGS="-L$BUILD_DIR/install/lib $CPPFLAGS" \
          cmake \
              -DBUILD_wireshark=OFF -DBUILD_sharkd=OFF -DBUILD_tshark=OFF \
              -DBUILD_capinfos=OFF -DBUILD_captype=OFF -DBUILD_dftest=OFF \
              -DBUILD_randpkt=OFF -DBUILD_dumpcap=OFF -DBUILD_rawshark=OFF \
              -DUSE_STATIC=ON -DENABLE_STATIC=ON -DENABLE_PLUGINS=OFF \
              -DBUILD_editcap=ON \
              -DBUILD_mergecap=ON \
              -DBUILD_reordercap=ON \
              -DBUILD_text2pcap=ON \
              -DENABLE_ZLIB=ON \
              ..

          # Build
          make
          output run/editcap
          output run/mergecap
          output run/text2pcap
          output run/reordercap
          popd
          echo "** Finished building wireshark"
      }

      function build_libpcap(){
          # Download/extract
          extract libpcap https://www.tcpdump.org/release tar.gz $LIBPCAP_VERSION

          # Configure
          CFLAGS="-I$BUILD_DIR/openssl-$OPENSSL_VERSION/include -DNETDB_INTERNAL=-1 $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/openssl-$OPENSSL_VERSION $LDFLAGS" \
          ./configure \
              --enable-remote \
              --disable-usb \
              --disable-netmap \
              --disable-bluetooth \
              --disable-dbus \
              --disable-rdma \
              --disable-shared \
              --prefix="$BUILD_DIR/install" \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make
          make install
          output rpcapd/rpcapd
          echo "** Finished building libpcap"
      }

      function build_tcpdump(){
          # Download/extract
          extract tcpdump https://www.tcpdump.org/release tar.gz $TCPDUMP_VERSION

          # The configure script fails to detect OpenSSL if DES is disabled...
          fgrep -rl DES_cbc_encrypt . \
          | xargs perl -i -pe 's/DES_cbc_encrypt/AES_cbc_encrypt/g'

          # Configure
          CFLAGS="-I$BUILD_DIR/openssl-$OPENSSL_VERSION/include -DNETDB_INTERNAL=-1 $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/openssl-$OPENSSL_VERSION $LDFLAGS" \
          ./configure \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make
          output tcpdump
          echo "** Finished building tcpdump"
      }

      function build_proberelay(){
          $CROSS_PFX-gcc \
              -I$BUILD_DIR/install/include $CFLAGS \
              -L$BUILD_DIR/install/lib $LDFLAGS \
              -o "$BIN_DIR/proberelay" \
              "$BUILD_DIR/proberelay.c" \
              -lpcap
          $STRIP "$BIN_DIR/proberelay"

          echo "** Finished building proberelay"
      }

      function build_ncurses() {
          # Download/extract
          extract ncurses https://invisible-mirror.net/archives/ncurses tar.gz $NCURSES_VERSION

          # Configure
          ./configure \
              --disable-shared \
              --enable-static \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make libs
          echo "** Finished building ncurses"
      }

      function build_zlib() {
          extract zlib https://zlib.net tar.gz $ZLIB_VERSION

          # Configure
          ./configure --static

          # Build
          make libz.a
          echo "** Finished building zlib"
      }

      function build_xz() {
          # Download/extract
          extract xz https://tukaani.org/xz tar.xz $XZ_VERSION

          # Configure
          ./configure \
              --disable-debug \
              --disable-dependency-tracking \
              --disable-silent-rules \
              --disable-shared \
              --disable-nls \
              --disable-lzmadec \
              --disable-lzmainfo \
              --disable-microlzma \
              --disable-lzip-decoder \
              --disable-scripts \
              --disable-doc \
              --enable-small \
              --enable-static \
              --prefix="$BUILD_DIR/install"

          # fuck it, we'll use violence to get static binaries
          sed -Ei \
              's/^(\s+..LIBTOOLFLAGS.\s+--mode=link.*)\\$/\1-all-static \\/' \
              src/xz{,dec}/Makefile

          # Build
          make install
          output "$BUILD_DIR/install/bin/xz"
      }

      function build_xzdec() {
          # Download/extract
          extract xz https://tukaani.org/xz tar.xz $XZ_VERSION

          # Configure for barebones xzdec
          ./configure \
              --disable-debug \
              --disable-dependency-tracking \
              --disable-silent-rules \
              --disable-shared \
              --disable-nls \
              --disable-lzmadec \
              --disable-lzmainfo \
              --disable-microlzma \
              --disable-lzip-decoder \
              --disable-scripts \
              --disable-doc \
              --enable-small \
              --enable-static \
              --enable-checks=crc32 \
              --enable-decoders=lzma1,lzma2,delta,x86,arm,armthumb,arm64 \
              --prefix="$BUILD_DIR/install" \
              --build=$MUSL_CROSS \
              --host=$MUSL_CROSS

          # fuck it, we'll use violence to get static binaries
          sed -Ei \
              's/^(\s+..LIBTOOLFLAGS.\s+--mode=link.*)\\$/\1-all-static \\/' \
              src/xz{,dec}/Makefile

          # Rebuild
          make clean
          make install
          output "$BUILD_DIR/install/bin/xzdec"

          # Multicall object
          cd src/xzdec
          sed -E 's/^[ ]*//' <<EoF >> Makefile

          xzdec-main.o: xzdec.c
          	\$(AM_V_CC)\$(CC) \$(DEFS) \$(DEFAULT_INCLUDES) \$(INCLUDES) \$(xzdec_CPPFLAGS) \$(CPPFLAGS) \$(AM_CFLAGS) \$(CFLAGS) -c -DXZDEC_MAIN=xzdec_main -o xzdec-main.o `test -f 'xzdec.c' || echo '\$(srcdir)/'`xzdec.c

          xzdec-multicall.o: xzdec-main.o \$(xzdec_DEPENDENCIES) \$(EXTRA_xzdec_DEPENDENCIES)
          	\$(AM_V_CCLD)\$(LINK) --entry xzdec_main -r xzdec-main.o \$(filter-out xzdec-xzdec.o,\$(xzdec_OBJECTS)) ../../src/liblzma/.libs/liblzma.a
      EoF

          make xzdec-main.o xzdec-multicall.o
          echo "** Finished building xzdec"
      }

      function build_lz4() {
          extract lz4 https://github.com/lz4 git $LZ4_VERSION
          make
          #output programs/lz4
          echo "** Finished building lz4"
      }

      function build_xxHash() {
          extract xxHash https://github.com/Cyan4973 git $XXHASH_VERSION
          make
          #output xxhsum
          echo "** Finished building xxHash"
      }

      function build_zstd() {
          extract zstd https://github.com/facebook git $ZSTD_VERSION

          make clean
          CFLAGS="-I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/lz4/lib $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          FLAGS="$CFLAGS $LDFLAGS -Os" \
          make zstd ZSTD_LEGACY_SUPPORT=0 \
                    HAVE_ZLIB=0 HAVE_LZMA=0 HAVE_LZ4=0 BACKTRACE=0
          output programs/zstd zstd-only
          CFLAGS="-I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/lz4/lib $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          FLAGS="$CFLAGS $LDFLAGS -Os" \
          make -C programs zstd-decompress ZSTD_LEGACY_SUPPORT=0 \
                    HAVE_ZLIB=0 HAVE_LZMA=0 HAVE_LZ4=0 BACKTRACE=0
          output programs/zstd-decompress unzstd

          make clean
          CFLAGS="-I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/lz4/lib $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          FLAGS="$CFLAGS $LDFLAGS -DZSTD_NO_UNUSED_FUNCTIONS -Os" \
          make zstd ZSTD_LEGACY_SUPPORT=0 \
                    HAVE_ZLIB=0 HAVE_LZMA=0 HAVE_LZ4=0 \
                    HAVE_THREAD=0 ZSTD_LIB_MINIFY=1 BACKTRACE=0 ZSTD_NO_INLINE=1
          output programs/zstd zstd-mini
          CFLAGS="-I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/lz4/lib $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          FLAGS="$CFLAGS $LDFLAGS -DZSTD_NO_UNUSED_FUNCTIONS -Os" \
          make -C programs zstd-decompress ZSTD_LEGACY_SUPPORT=0 ZSTD_NOCOMPRESS=1 \
                    HAVE_ZLIB=0 HAVE_LZMA=0 HAVE_LZ4=0 \
                    HAVE_THREAD=0 ZSTD_LIB_MINIFY=1 BACKTRACE=0 ZSTD_NO_INLINE=1
          output programs/zstd-decompress unzstd-mini

          make clean
          CFLAGS="-I$BUILD_DIR/install/include $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/install/lib $LDFLAGS" \
          FLAGS="$CFLAGS $LDFLAGS -DZSTD_NO_UNUSED_FUNCTIONS -Os" \
          make zstd ZSTD_LEGACY_SUPPORT=0 \
                    HAVE_ZLIB=0 HAVE_LZMA=1 HAVE_LZ4=0 \
                    HAVE_THREAD=0 ZSTD_LIB_MINIFY=1 BACKTRACE=0 ZSTD_NO_INLINE=1
          output programs/zstd zstd-xz-mini

          make clean
          CFLAGS="-I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/lz4/lib $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          FLAGS="$CFLAGS $LDFLAGS -O3" \
          make zstd BACKTRACE=0 ZSTD_LEGACY_SUPPORT=2
          output programs/zstd zstd-fast

          make clean
          CFLAGS="-I$BUILD_DIR/install/include -I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/lz4/lib $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/install/lib -L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          FLAGS="$CFLAGS $LDFLAGS -O3" \
          make zstd BACKTRACE=0 ZSTD_LEGACY_SUPPORT=2
          output programs/zstd zstd-full

          make clean
          CFLAGS="-I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/lz4/lib $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          FLAGS="$CFLAGS $LDFLAGS -Os" \
          make
          output programs/zstd

          echo "** Finished building zstd"
      }

      function build_readline() {
          # Download/extract
          extract readline https://ftp.gnu.org/gnu/readline tar.gz $READLINE_VERSION

          # Prevent building examples (which can't be done when cross-compiling)
          sed -i -e 's|examples/Makefile||g' configure.ac

          # Configure
          autoconf
          ./configure \
              --disable-shared \
              --enable-static \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make

          # Note that socat looks for readline in <readline/readline.h>, so we need
          # that directory to exist.
          ln -s "$BUILD_DIR/readline-$READLINE_VERSION" "$BUILD_DIR/readline"
          echo "** Finished building readline"
      }

      function build_dropbear() {
          # Download/extract
          extract dropbear https://github.com/mkj git DROPBEAR_$DROPBEAR_VERSION

          if [ ! -e configure ]; then
              autoconf; autoheader
          fi

          SAVED_CFLAGS="$CFLAGS"
          CFLAGS="$CFLAGS -Wno-undef"

          # Configure
          ./configure \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS \
              --enable-static \
              --prefix=/ \
              --exec-prefix=/usr \
              --disable-zlib \
              --disable-lastlog \
              --disable-utmp --disable-utmpx \
              --disable-wtmp --disable-wtmpx \
              --disable-pututline --disable-pututxline \
              --enable-bundled-libtom

          # Set build options
          sed -E 's/^\s*//' <<EoF > localoptions.h
              #define INETD_MODE 0

              #define DROPBEAR_SVR_LOCALTCPFWD 0
              #define DROPBEAR_SVR_REMOTETCPFWD 0
              #define DROPBEAR_SVR_AGENTFWD 0

              #define DROPBEAR_USER_ALGO_LIST 0
              #define DROPBEAR_CHACHA20POLY1305 0
              #define DROPBEAR_AES128 1
              #define DROPBEAR_AES256 1

              #define DROPBEAR_ENABLE_CTR_MODE 1
              #define DROPBEAR_ENABLE_CBC_MODE 0
              #define DROPBEAR_ENABLE_GCM_MODE 1

              #define DROPBEAR_SHA1_HMAC 0
              #define DROPBEAR_SHA1_96_HMAC 0
              #define DROPBEAR_SHA2_256_HMAC 1

              #define DROPBEAR_RSA 0
              #define DROPBEAR_DSS 0
              #define DROPBEAR_ECDSA 0
              #define DROPBEAR_ED25519 1

              #define DROPBEAR_SK_RSA DROPBEAR_RSA
              #define DROPBEAR_SK_DSS DROPBEAR_DSS
              #define DROPBEAR_SK_ECDSA DROPBEAR_ECDSA
              #define DROPBEAR_SK_ED25519 DROPBEAR_ED25519

              #define DROPBEAR_DH_GROUP14_SHA1 0
              #define DROPBEAR_DH_GROUP14_SHA256 0
              #define DROPBEAR_DH_GROUP16 0
              #define DROPBEAR_DH_GROUP1 0
              #define DROPBEAR_ECDH 0
              #define DROPBEAR_CURVE25519 1

              #define DROPBEAR_SFTPSERVER 0
              #define DO_MOTD 0
      EoF
          # update version string
          sed -En "s/^(#define\s+DROPBEAR_VERSION\s+\"[0-9.]+).*/\1+$(git log -1 --format=%h)\"/p" \
              sysoptions.h >> localoptions.h
          # hide version banner
          sed -Ei 's/^(#define\s+LOCAL_IDENT).*/\1 "SSH-2.0-dropbear"/' sysoptions.h
          # Enable the delay hostkey option by default
          sed -Ei 's/^(\s*svr_opts.delay_hostkey\s*=\s*)0;/\11;/' svr-runopts.c
          # fully disable RSA
          sed -Ei 's/^(#define DROPBEAR_RSA_SHA1) 1$/\1 DROPBEAR_RSA/' default_options.h
          # fully disable DSA
          sed -Ei 's/^(#define DROPBEAR_DSS) 1$/\1 0/' sysoptions.h

          # actually compile
          if [ "$MUSL_CROSS" = "x86_64-linux-musl" ]; then
              sed -Ei 's/^(#define DROPBEAR_RSA) 0$/\1 1/' localoptions.h
              sed -Ei 's/^(#define DROPBEAR_ECDSA) 0$/\1 1/' localoptions.h
              sed -Ei 's/^(#define DROPBEAR_DSS) 0$/\1 1/' localoptions.h
              sed -Ei 's/^(#define DROPBEAR_DSS) 0$/\1 1/' sysoptions.h
              make PROGRAMS='dropbearconvert dropbearkey' MULTI=1
              output dropbearmulti dbkeyconv
          else
              export LTM_CFLAGS='-Os'
              make PROGRAMS='dropbear'
              output dropbear

              make PROGRAMS='dbclient'
              output dbclient

              make clean
              CFLAGS="$CFLAGS -DDROPBEARKEY_RETURN_TRUE=1" \
              make PROGRAMS='dropbear dropbearkey' MULTI=1
              output dropbearmulti dbmulti

              make clean
              CFLAGS="$CFLAGS -DDROPBEARKEY_RETURN_TRUE=1" \
              make PROGRAMS='dropbear dbclient dropbearkey' MULTI=1
              output dropbearmulti dbmulti-cli

              make clean
              CFLAGS="$CFLAGS -DDROPBEARKEY_RETURN_TRUE=1" \
              make PROGRAMS='dropbear dropbearconvert dropbearkey' MULTI=1
              output dropbearmulti dbmulti-conv

              make clean
              make PROGRAMS='dropbear dropbearkey' MULTI=1
              output dropbearmulti dbmulti-key

              make clean
              CFLAGS="$CFLAGS -DDROPBEARKEY_RETURN_TRUE=1" \
              make PROGRAMS='dropbear scp dropbearkey' MULTI=1
              output dropbearmulti dbmulti-scp

              make clean
              CFLAGS="$CFLAGS -DDROPBEARKEY_RETURN_TRUE=1" \
              make PROGRAMS='dropbear dbclient dropbearconvert dropbearkey' MULTI=1
              output dropbearmulti dbmulti-cli-conv

              make clean
              make PROGRAMS='dropbear dbclient dropbearkey' MULTI=1
              output dropbearmulti dbmulti-cli-key

              make clean
              CFLAGS="$CFLAGS -DDROPBEARKEY_RETURN_TRUE=1" \
              make PROGRAMS='dropbear dbclient scp dropbearkey' MULTI=1
              output dropbearmulti dbmulti-cli-scp

              make clean
              make PROGRAMS='dropbear dropbearconvert dropbearkey' MULTI=1
              output dropbearmulti dbmulti-conv-key

              make clean
              CFLAGS="$CFLAGS -DDROPBEARKEY_RETURN_TRUE=1" \
              make PROGRAMS='dropbear dropbearconvert scp dropbearkey' MULTI=1
              output dropbearmulti dbmulti-conv-scp

              make clean
              make PROGRAMS='dropbear dropbearkey scp' MULTI=1
              output dropbearmulti dbmulti-key-scp

              make clean
              make PROGRAMS='dropbear dbclient dropbearconvert dropbearkey' MULTI=1
              output dropbearmulti dbmulti-cli-conv-key

              make clean
              CFLAGS="$CFLAGS -DDROPBEARKEY_RETURN_TRUE=1" \
              make PROGRAMS='dropbear dbclient dropbearconvert scp dropbearkey' MULTI=1
              output dropbearmulti dbmulti-cli-conv-scp

              make clean
              make PROGRAMS='dropbear dbclient dropbearkey scp' MULTI=1
              output dropbearmulti dbmulti-cli-key-scp

              make clean
              make PROGRAMS='dropbear dropbearconvert dropbearkey scp' MULTI=1
              output dropbearmulti dbmulti-conv-key-scp

              make clean
              make PROGRAMS='dropbear dbclient dropbearconvert dropbearkey scp' MULTI=1
              output dropbearmulti dbmulti-cli-conv-key-scp
          fi
          echo "** Finished building dropbear"
          CFLAGS="$SAVED_CFLAGS"
      }

      function build_socat() {
          # Download/extract
          extract socat http://www.dest-unreach.org/socat/download tar.gz $SOCAT_VERSION

          # Configure
          SOURCE_DATE_EPOCH="$(date -r CHANGES '+%s')" \
          BUILD_DATE="$(date -r CHANGES '+%b %e %Y %H:%M:%S')" \
          CFLAGS="-I$BUILD_DIR -I$BUILD_DIR/openssl-$OPENSSL_VERSION/include -DNETDB_INTERNAL=-1 $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/readline-$READLINE_VERSION -L$BUILD_DIR/ncurses-$NCURSES_VERSION/lib -L$BUILD_DIR/openssl-$OPENSSL_VERSION $LDFLAGS" \
          LIBS="$BUILD_DIR/ncurses-$NCURSES_VERSION/lib/libncurses.a" \
          ./configure \
              --enable-openssl-base=$BUILD_DIR/openssl-$OPENSSL_VERSION \
              --enable-openssl \
              --enable-msglevel=info \
              --disable-tun \
              --disable-sctp \
              --disable-vsock \
              --disable-readline \
              --disable-sycls \
              --disable-filan \
              --disable-udplite \
              --disable-dccp \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          sed -Ei 's/#define\s+HAVE_GETPROTOBYNUMBER_R.*/#define HAVE_GETPROTOBYNUMBER_R 0/' config.h

          # Build
          SOURCE_DATE_EPOCH="$(date -r CHANGES '+%s')" \
          BUILD_DATE="$(date -r CHANGES '+%b %e %Y %H:%M:%S')" \
          make
          output socat socat-openssl

          make clean
          SOURCE_DATE_EPOCH="$(date -r CHANGES '+%s')" \
          BUILD_DATE="$(date -r CHANGES '+%b %e %Y %H:%M:%S')" \
          CFLAGS="-I$BUILD_DIR -DNETDB_INTERNAL=-1 $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/readline-$READLINE_VERSION -L$BUILD_DIR/ncurses-$NCURSES_VERSION/lib $LDFLAGS" \
          LIBS="$BUILD_DIR/ncurses-$NCURSES_VERSION/lib/libncurses.a" \
          ./configure \
              --disable-openssl \
              --enable-msglevel=info \
              --disable-tun \
              --disable-sctp \
              --disable-vsock \
              --disable-readline \
              --disable-sycls \
              --disable-filan \
              --disable-udplite \
              --disable-dccp \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          sed -Ei 's/#define\s+HAVE_GETPROTOBYNUMBER_R.*/#define HAVE_GETPROTOBYNUMBER_R 0/' config.h

          # Build
          SOURCE_DATE_EPOCH="$(date -r CHANGES '+%s')" \
          BUILD_DATE="$(date -r CHANGES '+%b %e %Y %H:%M:%S')" \
          make
          output socat

          echo "** Finished building socat"
      }

      function build_rsync() {
          # Download/extract
          extract rsync https://download.samba.org/pub/rsync/src tar.gz $RSYNC_VERSION

          OPTS="--disable-roll-simd --disable-roll-asm --disable-md2man --disable-debug --disable-locale"
          if [ "$MUSL_CROSS" != "x86_64-linux-musl" ]; then
              OPTS="$OPTS"
          else
              OPTS="$OPTS"
          fi

          # Configure
          CFLAGS="-I$BUILD_DIR/openssl-$OPENSSL_VERSION/include -I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/xxHash -I$BUILD_DIR/zstd/lib -I$BUILD_DIR/lz4/lib $CFLAGS" \
          CXXFLAGS="$CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/openssl-$OPENSSL_VERSION -L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/xxHash -L$BUILD_DIR/zstd/lib -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          ./configure \
              --disable-debug $OPTS \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make
          output rsync rsync-openssl

          make clean
          # Configure
          CFLAGS="-I$BUILD_DIR/zlib-$ZLIB_VERSION -I$BUILD_DIR/xxHash -I$BUILD_DIR/zstd/lib -I$BUILD_DIR/lz4/lib $CFLAGS" \
          CXXFLAGS="$CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/zlib-$ZLIB_VERSION -L$BUILD_DIR/xxHash -L$BUILD_DIR/zstd/lib -L$BUILD_DIR/lz4/lib $LDFLAGS" \
          ./configure \
              --disable-debug $OPTS \
              --disable-openssl \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make
          output rsync

          echo "** Finished building rsync"
      }

      function build_libsodium(){
          # Download/extract
          extract libsodium https://github.com/jedisct1 git $LIBSODIUM_VERSION

          # Configure
          ./configure \
              --enable-static \
              --disable-shared \
              --disable-asm \
              --disable-ssp \
              --without-pthreads \
              --prefix="$BUILD_DIR/install" \
              --build=x86_64-linux-gnu \
              --host=$MUSL_CROSS

          # Build
          make install
          echo "** Finished building libsodium"
      }

      function build_minisign(){
          # Download/extract
          extract minisign https://github.com/ryancdotorg git $MINISIGN_VERSION

          # Build
          WITH_PTHREADS=0 \
          CC="$CROSS_PFX-gcc" \
          CFLAGS="-I$BUILD_DIR/install/include $CFLAGS" \
          LDFLAGS="-L$BUILD_DIR/install/lib $LDFLAGS" \
          make bin/miniverify bin/minisign \
               obj/miniverify_multicall.o \
               obj/minisign_multicall.o
          output bin/miniverify
          output bin/minisign
          echo "** Finished building minisign"
      }

      function build_sha2sum(){
          # Download/extract
          extract sha2sum https://github.com/ryancdotorg git $SHA2SUM_VERSION

          # Build
          CFLAGS="-I$BUILD_DIR/install/include $CFLAGS" \
          make bin/sha2sum bin/sha256sum \
              obj/sha256sum_multicall.o \
              obj/sha2sum_nacl_sha512_multicall.o
          output bin/sha2sum
          output bin/sha256sum
          echo "** Finished building sha2sum"
      }

      function build_multicall(){
          # Download/extract
          extract multicall https://github.com/ryancdotorg git $MULTICALL_VERSION

          # Build
          LDFLAGS="-L$BUILD_DIR/install/lib $LDFLAGS" \
          make bin/multicall-miniverify-sha256sum{,-xzdec} \
               bin/multicall-mini{verify,sign}-sha2sum{,-xzdec}
          output bin/multicall-miniverify-sha256sum
          output bin/multicall-miniverify-sha256sum-xzdec
          output bin/multicall-miniverify-sha2sum
          output bin/multicall-miniverify-sha2sum-xzdec
          output bin/multicall-minisign-sha2sum
          output bin/multicall-minisign-sha2sum-xzdec
          echo "** Finished building multicall"
      }



      function unpack_patches() {
      # tar -C BUILD_DIR -cz --owner=0 --group=0 patches xxd.c | base64 -w79 \
      # | sed -e '/[<]_eof/,/^_eof/{//!d;r /dev/stdin' -e '}' builder.sh \
      # | sponge builder.sh
      base64 -d <<_eof | tar -C "$1" -xvz
[encoded data, 27950 characters]
      zZ/78bp//B3xMHIIAGAEA
      _eof
      }

      function buildall() {
          [ -d "$BUILD_DIR/install" ] && rm -rf "$BUILD_DIR/install"
          # setcross "$1"
          setnative "$1"

          DISABLE_WIRESHARK=""

          if [ "$MUSL_CROSS" = "mips-linux-muslsf" ]; then
              DISABLE_WIRESHARK="1"
          fi

          get_musl

          ${CROSS_PFX}gcc $CFLAGS $LDFLAGS -o "$BIN_DIR/xxd" "$BUILD_DIR/xxd.c"
          $STRIP "$BIN_DIR/xxd"

          ${CROSS_PFX}gcc $CFLAGS $LDFLAGS -o "$BIN_DIR/sav" "$BUILD_DIR/sav.c"
          $STRIP "$BIN_DIR/sav"

          ${CROSS_PFX}gcc $CFLAGS $LDFLAGS -o "$BIN_DIR/pause" "$BUILD_DIR/pause.c" -nostartfiles
          $STRIP "$BIN_DIR/pause"

          build_xzdec

          build_pv

          build_zlib

          build_xz
          build_lz4
          build_zstd
      }

      function main() {
          HASH=$(sha256sum $0|head -c16)
          mkdir -p "$BUILD_DIR"

          if [ ! -f .gitignore ]; then
              echo -e 'output\npatches\n.gitignore' > .gitignore
          fi

          if [ ! -d "$BUILD_DIR/patches" ]; then
              unpack_patches "$BUILD_DIR"
          fi

          if [ ! -z "$1" ]; then
              if [ "$1" = "unpack" ]; then
                  true
              elif [ "$1" = "repack" -a -d "$BUILD_DIR/patches" ]; then
                  cp -a $0 $0.bak
                  tar -C $BUILD_DIR -cz --owner=0 --group=0 patches xxd.c sav.c proberelay.c pause.c | base64 -w79 \
                  | sed -e '/[<]_eof/,/^_eof/{//!d;r /dev/stdin' -e '}' $0 \
                  | sponge $0
              else
                  buildall "$1"
              fi
              exit 0
          fi

          # armel-linux-musleabihf
          # mips-linux-musl mips-linux-muslsf # mipsel-linux-musl mipsel-linux-muslsf mipsel-linux-musln32 mipsel-linux-musln32sf
          for arch in armv7l-linux-musleabihf x86_64-linux-musl mips-linux-muslsf armv5l-linux-musleabihf aarch64-linux-musl
          do
              echo "** building for $arch **"
              export arch
              export PS4="+$arch+ "
              buildall "$arch"
              echo "** finished $arch bins **"
          done

          echo "** Finished **"
      }

      main "$@"
      # vim:sw=4:ts=4:et:
    BUILDER_EOF
    Kernel.system "bash ./crew-static-builder.sh #{@cross}"
  end

  def self.install
    FileUtils.install "output/#{@cross}/zstd-full", "#{CREW_DEST_PREFIX}/bin/zstd", mode: 0o755
    FileUtils.install "output/#{@cross}/zstd-full", "#{CREW_DEST_PREFIX}/bin/zstd-static", mode: 0o755
  end
end
