#!/usr/bin/env bash # Builds the rsync that ships inside M8Thor.app. # # Apple Silicon (arm64) only — M8Thor does not support Intel Macs. macOS 14+, linked against # system libraries only, built natively so configure's run-time checks see the real system. # xxhash is compiled in statically: rsync's fastest checksums, about ten times quicker than # its built-in MD5 when --checksum hashes a backup on a local disk. # # The unmodified upstream sources (rsync, xxHash) and this script are the Corresponding Source # for the GPLv3 binary; they ship in the app next to it (Contents/Resources/ThirdParty/rsync). # # Usage: Scripts/build-rsync.sh → writes Vendor/rsync/ # # Upgrading: change the version and SHA-256 (rsync: verify the upstream .asc signature first; # xxHash: compare with an independent source such as Homebrew's formula), run the script, then # the full test suite — RsyncCommand.detectVersion must know the new rsync version. set -euo pipefail VERSION="3.4.4" SHA256="bd88cf82fa653da32314fb229136407c5c90f80d1758d8f4b091767877d8fa96" URL="https://download.samba.org/pub/rsync/src/rsync-${VERSION}.tar.gz" XXHASH_VERSION="0.8.3" XXHASH_SHA256="aae608dfe8213dfd05d909a57718ef82f30722c392344583d3f39050c7f29a80" XXHASH_URL="https://github.com/Cyan4973/xxHash/archive/refs/tags/v${XXHASH_VERSION}.tar.gz" MIN_MACOS="14.0" # OpenSSL, zstd and lz4 would have to ship as well; M8Thor copies locally without compression. # popt and zlib come from the rsync source tree itself. CONFIGURE_FLAGS=( --enable-xxhash --disable-openssl --disable-zstd --disable-lz4 --disable-md2man --disable-debug --with-included-popt --with-included-zlib ) CFLAGS_COMMON="-arch arm64 -O2 -mmacosx-version-min=${MIN_MACOS}" REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" OUT="$REPO_ROOT/Vendor/rsync" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT # A cross build answers configure's run-time checks with pessimistic defaults (no socketpairs, # no hardlinked symlinks), so the binary is built on the architecture it ships for. if [[ "$(uname -m)" != "arm64" ]]; then echo "✗ Build on an Apple Silicon Mac: the binary ships for arm64 only" >&2 exit 1 fi # fetch : the vendored copy when present, else the upstream download. fetch() { local name="$1" url="$2" sha="$3" if [[ -f "$OUT/$name" ]]; then cp "$OUT/$name" "$WORK/$name" else curl -fsSL --retry 3 -o "$WORK/$name" "$url" fi echo "${sha} $WORK/$name" | shasum -a 256 -c - >/dev/null echo "✓ $name verified (sha256)" } fetch "rsync-${VERSION}.tar.gz" "$URL" "$SHA256" fetch "xxHash-${XXHASH_VERSION}.tar.gz" "$XXHASH_URL" "$XXHASH_SHA256" # xxhash as a static library only, so rsync cannot pick up a dylib at run time. XXH="$WORK/xxhash" mkdir -p "$XXH/src" "$XXH/include" "$XXH/lib" tar -xzf "$WORK/xxHash-${XXHASH_VERSION}.tar.gz" -C "$XXH/src" --strip-components 1 clang $CFLAGS_COMMON -c "$XXH/src/xxhash.c" -o "$XXH/xxhash.o" ar rcs "$XXH/lib/libxxhash.a" "$XXH/xxhash.o" cp "$XXH/src/xxhash.h" "$XXH/include/" echo "✓ Built libxxhash.a" SRC="$WORK/build" mkdir -p "$SRC" tar -xzf "$WORK/rsync-${VERSION}.tar.gz" -C "$SRC" --strip-components 1 ( cd "$SRC" CC="clang -arch arm64" \ CFLAGS="-O2 -mmacosx-version-min=${MIN_MACOS}" \ CPPFLAGS="-I$XXH/include" \ LDFLAGS="-mmacosx-version-min=${MIN_MACOS} -L$XXH/lib" \ ./configure "${CONFIGURE_FLAGS[@]}" >"$WORK/configure.log" 2>&1 \ || { tail -30 "$WORK/configure.log"; exit 1; } make -j"$(sysctl -n hw.ncpu)" rsync >"$WORK/make.log" 2>&1 \ || { tail -30 "$WORK/make.log"; exit 1; } ) echo "✓ Built rsync (arm64)" mkdir -p "$OUT" cp "$SRC/rsync" "$OUT/rsync" strip -x "$OUT/rsync" chmod 755 "$OUT/rsync" # The capabilities configure detected, as the binary itself reports them. VERSION_TEXT="$("$OUT/rsync" --version)" if grep -qE 'no (socketpairs|hardlink-symlinks|hardlink-specials)' <<<"$VERSION_TEXT"; then echo "✗ rsync was configured without a capability macOS has" >&2 exit 1 fi if ! grep -A1 '^Checksum list' <<<"$VERSION_TEXT" | grep -q 'xxh128'; then echo "✗ rsync was built without xxhash checksums" >&2 exit 1 fi # Only system libraries may remain: anything else would not exist on the user's Mac. if otool -L "$OUT/rsync" | tail -n +2 | grep -vE '^\s+/usr/lib/|^\s+/System/'; then echo "✗ rsync links a non-system library" >&2 exit 1 fi # License texts and the exact sources travel with the binary. cp "$WORK/rsync-${VERSION}.tar.gz" "$OUT/rsync-${VERSION}.tar.gz" cp "$WORK/xxHash-${XXHASH_VERSION}.tar.gz" "$OUT/xxHash-${XXHASH_VERSION}.tar.gz" cp "$SRC/COPYING" "$OUT/COPYING" # Compiled into the binary, under their own permissive licenses. cp "$SRC/popt/COPYING" "$OUT/popt-COPYING" sed -n '4,23p' "$SRC/zlib/zlib.h" > "$OUT/zlib-LICENSE" cp "$XXH/src/LICENSE" "$OUT/xxhash-LICENSE" cp "$REPO_ROOT/Scripts/build-rsync.sh" "$OUT/build-rsync.sh" echo "✓ Vendor/rsync ready: $(lipo -archs "$OUT/rsync") — $(head -1 <<<"$VERSION_TEXT")"