#!/bin/zsh
# Builds the archive engines from pinned sources, universal (arm64 + x86_64), macOS 14+:
#   build/lib/*.a + build/include   libarchive (+ xz, zstd, lz4; zlib, bzip2, iconv, libxml2 and CommonCrypto from the SDK)
#   build/lib/libunrar.a            UnRAR library (RARLAB licence: extraction only)
#   build/bin/7zz                   7-Zip console (LGPL), shipped as a separate helper executable
#   build/bin/unar, build/bin/lsar  XADMaster (The Unarchiver's engine, LGPL): StuffIt, BinHex, MacBinary, AppleSingle,
#                                   legacy filename encodings… (patched: patches/xadmaster-password-stdin.sh)
# Usage: Vendor/build-engines.sh   (idempotent; delete build/ to rebuild)
set -euo pipefail
cd "$(dirname "$0")"
VENDOR=$PWD SRC=$PWD/src OUT=$PWD/build WORK=$PWD/build/work
export MACOSX_DEPLOYMENT_TARGET=14.0
ARCHS="arm64;x86_64"
JOBS=$(sysctl -n hw.ncpu)
mkdir -p "$SRC" "$OUT"/{lib,include,bin} "$WORK"

fetch() { # name url sha256
  local file="$SRC/$1"
  [ -f "$file" ] || curl -sSfL "$2" -o "$file"
  echo "$3  $file" | shasum -a 256 -c --quiet - || { echo "checksum mismatch: $1" >&2; exit 1; }
}
fetch libarchive-3.8.10.tar.xz https://www.libarchive.org/downloads/libarchive-3.8.10.tar.xz 56cad765459d5ee25a3b761f90c47d99379d28297fbfb72d908880d6b875fb96
fetch unrarsrc-7.3.2.tar.gz https://www.rarlab.com/rar/unrarsrc-7.3.2.tar.gz f61a1160d6e2ebbda2ad353c8e82f62ab4312f97fde23c6c2c982d25e0014f99
fetch 7z2605-src.tar.xz https://github.com/ip7z/7zip/releases/download/26.05/7z2605-src.tar.xz 0b6080b8c3e7a579161d2d495224c0e51c467576cb4c7048b0ab485ef44cc22e
fetch zstd-1.5.7.tar.gz https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-1.5.7.tar.gz eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3
fetch xz-5.8.4.tar.xz https://github.com/tukaani-project/xz/releases/download/v5.8.4/xz-5.8.4.tar.xz 4ce24038fd4221e0d13bc1a2de7a4db56e90b92b3bf75321f6c14be73f65de4b
fetch XADMaster-1.10.8.tar.gz https://codeload.github.com/MacPaw/XADMaster/tar.gz/refs/tags/v1.10.8 652953d7988b3c33f4f52b61c357afd1a7c2fc170e5e6e2219f4432b0c4cd39f
fetch universal-detector-1.1.tar.gz https://codeload.github.com/MacPaw/universal-detector/tar.gz/refs/tags/1.1 8e8532111d0163628eb828a60d67b53133afad3f710b1967e69d3b8eee28a811
fetch lz4-1.10.0.tar.gz https://github.com/lz4/lz4/releases/download/v1.10.0/lz4-1.10.0.tar.gz 537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b

# Homebrew's copies must never be picked up: the app ships only what is built here.
CMAKE_COMMON=(-DCMAKE_BUILD_TYPE=Release "-DCMAKE_OSX_ARCHITECTURES=$ARCHS" -DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET
  -DCMAKE_INSTALL_PREFIX="$OUT" -DCMAKE_PREFIX_PATH="$OUT" "-DCMAKE_IGNORE_PREFIX_PATH=/opt/homebrew;/usr/local"
  -DBUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON)

cmake_build() { # name source-subdir extra-args...
  local name=$1 dir=$2; shift 2
  [ -f "$WORK/$name.done" ] && return
  echo "▸ $name"
  cmake -S "$dir" -B "$WORK/$name-build" "${CMAKE_COMMON[@]}" "$@" >"$WORK/$name.log" 2>&1
  cmake --build "$WORK/$name-build" -j "$JOBS" >>"$WORK/$name.log" 2>&1
  cmake --install "$WORK/$name-build" >>"$WORK/$name.log" 2>&1
  touch "$WORK/$name.done"
}

cd "$WORK"
[ -d zstd-1.5.7 ] || tar -xzf "$SRC/zstd-1.5.7.tar.gz"
[ -d xz-5.8.4 ] || tar -xJf "$SRC/xz-5.8.4.tar.xz"
[ -d lz4-1.10.0 ] || tar -xzf "$SRC/lz4-1.10.0.tar.gz"
[ -d libarchive-3.8.10 ] || tar -xJf "$SRC/libarchive-3.8.10.tar.xz"

cmake_build zstd zstd-1.5.7/build/cmake -DZSTD_BUILD_SHARED=OFF -DZSTD_BUILD_PROGRAMS=OFF -DZSTD_BUILD_TESTS=OFF
cmake_build xz xz-5.8.4 -DXZ_NLS=OFF -DXZ_DOC=OFF -DXZ_TOOL_XZ=OFF -DXZ_TOOL_XZDEC=OFF -DXZ_TOOL_LZMADEC=OFF \
  -DXZ_TOOL_LZMAINFO=OFF -DXZ_TOOL_SCRIPTS=OFF -DXZ_TOOL_SYMLINKS=OFF -DXZ_TOOL_SYMLINKS_LZMA=OFF -DBUILD_TESTING=OFF
cmake_build lz4 lz4-1.10.0/build/cmake -DLZ4_BUILD_CLI=OFF -DBUILD_STATIC_LIBS=ON
cmake_build libarchive libarchive-3.8.10 \
  -DENABLE_TAR=OFF -DENABLE_CPIO=OFF -DENABLE_CAT=OFF -DENABLE_UNZIP=OFF -DENABLE_TEST=OFF -DENABLE_INSTALL=ON \
  -DENABLE_OPENSSL=OFF -DENABLE_MBEDTLS=OFF -DENABLE_NETTLE=OFF -DENABLE_CNG=OFF -DENABLE_LIBB2=OFF -DENABLE_LZO=OFF \
  -DENABLE_EXPAT=OFF -DENABLE_LIBXML2=ON -DENABLE_ICONV=ON -DENABLE_ZLIB=ON -DENABLE_BZip2=ON \
  -DENABLE_LZMA=ON -DLIBLZMA_INCLUDE_DIR="$OUT/include" -DLIBLZMA_LIBRARY="$OUT/lib/liblzma.a" \
  -DENABLE_ZSTD=ON -DZSTD_INCLUDE_DIR="$OUT/include" -DZSTD_LIBRARY="$OUT/lib/libzstd.a" \
  -DENABLE_LZ4=ON -DLZ4_INCLUDE_DIR="$OUT/include" -DLZ4_LIBRARY="$OUT/lib/liblz4.a"

# UnRAR: the library objects (RARDLL), archived statically instead of the makefile's shared library.
if [ ! -f "$WORK/unrar.done" ]; then
  echo "▸ unrar"
  rm -rf unrar && tar -xzf "$SRC/unrarsrc-7.3.2.tar.gz"
  (cd unrar && make -j "$JOBS" lib CXX=clang++ STRIP=true \
     CXXFLAGS="-O2 -std=c++11 -arch arm64 -arch x86_64 -mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET -Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else" \
     >"$WORK/unrar.log" 2>&1 || true
   ls *.o >/dev/null && rm -f "$OUT/lib/libunrar.a" && ar rcs "$OUT/lib/libunrar.a" *.o)
  mkdir -p "$OUT/include/unrar" && cp unrar/dll.hpp "$OUT/include/unrar/"
  cp unrar/license.txt "$OUT/UNRAR-LICENSE.txt"
  touch "$WORK/unrar.done"
fi

# 7-Zip console (7zz), one build per architecture, then one universal binary.
if [ ! -f "$WORK/7zip.done" ]; then
  echo "▸ 7-zip"
  rm -rf 7zip && mkdir 7zip && tar -xJf "$SRC/7z2605-src.tar.xz" -C 7zip
  # 7-Zip's makefiles target macOS 10.15 / 11, which the current libc++ refuses: set the architecture flags ourselves.
  for arch in arm64:arm64 x64:x86_64; do
    (cd 7zip/CPP/7zip/Bundles/Alone2 && make -j "$JOBS" -f ../../cmpl_mac_${arch%%:*}.mak \
       MY_ARCH="-arch ${arch##*:} -mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET" >"$WORK/7zip-${arch%%:*}.log" 2>&1)
  done
  lipo -create 7zip/CPP/7zip/Bundles/Alone2/b/m_arm64/7zz 7zip/CPP/7zip/Bundles/Alone2/b/m_x64/7zz -output "$OUT/bin/7zz"
  cp 7zip/DOC/License.txt "$OUT/7ZIP-LICENSE.txt"
  touch "$WORK/7zip.done"
fi

# XADMaster: its Xcode project expects ../UniversalDetector next to it.
if [ ! -f "$WORK/xad.done" ]; then
  echo "▸ xadmaster"
  rm -rf XADMaster UniversalDetector xad-dd
  tar -xzf "$SRC/XADMaster-1.10.8.tar.gz" && mv XADMaster-1.10.8 XADMaster
  tar -xzf "$SRC/universal-detector-1.1.tar.gz" && mv universal-detector-1.1 UniversalDetector
  "$VENDOR/patches/xadmaster-password-stdin.sh" "$WORK/XADMaster"
  for tool in unar lsar; do
    xcodebuild -project XADMaster/XADMaster.xcodeproj -scheme $tool -configuration Release -derivedDataPath xad-dd \
      ARCHS="arm64 x86_64" ONLY_ACTIVE_ARCH=NO MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET CODE_SIGNING_ALLOWED=NO \
      build >"$WORK/xad-$tool.log" 2>&1
    cp xad-dd/Build/Products/Release/$tool "$OUT/bin/"
  done
  cp XADMaster/LICENSE "$OUT/XADMASTER-LICENSE.txt"
  touch "$WORK/xad.done"
fi

echo "✓ engines in $OUT"
lipo -info "$OUT"/lib/libarchive.a "$OUT"/lib/libunrar.a "$OUT"/bin/7zz "$OUT"/bin/unar "$OUT"/bin/lsar
