#!/bin/bash
# Build the Squid bundle that Squid Proxy Professional ships.
#
# Run from a Cygwin login shell (see BUILD.md):
#   C:\cygwin64\bin\bash.exe -l "/cygdrive/c/Squid Proxy Professional/squid-build/build-squid.sh"
#
# Inputs  (tracked):  source/squid-<ver>.tar.gz, patches/
# Output  (ignored):  bundle/  - read by the installer; FinalBuilder signs
#                     bundle/sbin/squid.exe
# Scratch (deleted):  C:\squid-work - autotools cannot build in a path with
#                     spaces, so the build never runs inside the repository.
set -euo pipefail

VER=7.7
HERE="$(cd "$(dirname "$0")" && pwd)"
WORK=/cygdrive/c/squid-work
PREFIX=$WORK/install
SRC=$WORK/squid-$VER

echo "== Squid $VER: fresh build in $WORK"
rm -rf "$WORK"
mkdir -p "$WORK/build"

# --- source, with the one build-file patch ---------------------------------
tar -xzf "$HERE/source/squid-$VER.tar.gz" -C "$WORK"
# Upstream name inside the tree; ours is per-version so shipped sets never collide.
cp "$HERE/patches/squid-$VER-version.rc" "$SRC/src/squid-version.rc"
( cd "$SRC"
  patch -p1 < "$HERE/patches/squid-$VER-versioninfo.patch"
  # --foreign matches Squid's own automake strictness. Newer automake than the
  # tarball's is fine: the regenerated src/Makefile.in differs only by our lines.
  automake --foreign src/Makefile )

# --- configure + build -------------------------------------------------------
# --without-nettle is REQUIRED. Cygwin's nettle 4.0 makes base64_decode_update
# treat its length argument as buffer capacity; Squid passes 0 at every call
# site, so every decode fails and ALL proxy authentication is rejected, with a
# clean build and no warning. Without nettle Squid uses its own base64 and MD5.
# Upstream fix pending: github.com/squid-cache/squid/pull/2296 - if it merges as
# written it changes Squid's bundled base64 too; rerun test-bundle.ps1.
#
# No -march=native: the binary must run on any x86-64-v2 CPU, not this one.
cd "$WORK/build"
CFLAGS="-O2 -DNDEBUG -march=x86-64-v2" CXXFLAGS="-O2 -DNDEBUG -march=x86-64-v2" \
"$SRC/configure" \
  --prefix="$PREFIX" \
  --with-openssl \
  --without-nettle \
  --disable-strict-error-checking \
  --enable-external-acl-helpers='delayer file_userip session unix_group' \
  > "$WORK/configure.log" 2>&1
make -j"$(nproc)" > "$WORK/make.log" 2>&1
make install-strip > "$WORK/install.log" 2>&1

# --- make it a standalone bundle ---------------------------------------------
# Copy every Cygwin DLL each directory's executables actually import, found
# with cygcheck rather than a fixed list: sonames move between Cygwin releases.
for dir in sbin libexec; do
  for exe in "$PREFIX/$dir"/*.exe; do
    cygcheck "$(cygpath -w "$exe")" 2>/dev/null
  done | tr -d '\r' | grep -ioE 'C:\\cygwin64\\bin\\cyg[^\\ ]+\.dll' \
       | sed 's/.*\\//' | sort -u > "$WORK/$dir-dlls.txt"
  while read -r dll; do cp -f "/usr/bin/$dll" "$PREFIX/$dir/"; done < "$WORK/$dir-dlls.txt"
  echo "   $dir: $(wc -l < "$WORK/$dir-dlls.txt") DLLs: $(tr '\n' ' ' < "$WORK/$dir-dlls.txt")"
done

# Cygwin resolves /dev/shm next to the cygwin1.dll it loaded; without it
# shm_open fails and Squid dies at startup.
mkdir -p "$PREFIX/dev/shm"

# Prove each directory resolves every DLL locally, with Cygwin off PATH, so a
# missing DLL is reported instead of being found in C:\cygwin64.
leaks=0
for dir in sbin libexec; do
  for exe in "$PREFIX/$dir"/*.exe; do
    out=$(cd "$PREFIX/$dir" && PATH=/cygdrive/c/Windows/System32 /usr/bin/cygcheck ".\\$(basename "$exe")" 2>&1 \
          | tr -d '\r' | grep -iE 'could not find|cygwin64' || true)
    if [ -n "$out" ]; then echo "   LEAK $dir/$(basename "$exe"): $out"; leaks=$((leaks+1)); fi
  done
done
[ "$leaks" -eq 0 ] || { echo "== FAILED: $leaks executables are not self-contained"; exit 1; }

# --- hand the bundle to the repository ----------------------------------------
rm -rf "$HERE/bundle"
cp -a "$PREFIX" "$HERE/bundle"
rm -rf "$HERE/bundle/var"

# Do not run the bundle from here: inside a Cygwin shell the shell's own
# cygwin1.dll is already loaded and the bundle's helpers cannot fork. Test it
# from PowerShell with test-bundle.ps1.
echo "== OK: Squid $VER bundle in $HERE/bundle"
echo "   next: test-bundle.ps1 (from PowerShell), then FinalBuilder"
