#!/usr/bin/env bash set -euo pipefail # ============================================================ # Borg 2.0.0b5 One-File Binary Builder (Variant B: without FUSE/mount) # Target host for build: Debian 12 (Bookworm) # Output binary: /opt/borg2-b5-build/dist/borg2-b5 # ============================================================ BORG_TAG="2.0.0b5" VENV_DIR="/opt/borg2-b5-build" SRC_DIR="/opt/borg-b5-src" BIN_NAME="borg2-b5-nofuse" if [[ $EUID -ne 0 ]]; then echo "[WARN] Not running as root. I will skip 'apt install'. Ensure prerequisites are installed:" echo " apt install -y git python3-venv python3-dev build-essential pkg-config \\ libssl-dev libxxhash-dev liblz4-dev libzstd-dev libacl1-dev \\ liblzma-dev libb2-dev ca-certificates" else echo "[INFO] Installing OS prerequisites via apt..." export DEBIAN_FRONTEND=noninteractive apt update -y apt install -y git python3-venv python3-dev build-essential pkg-config \ libssl-dev libxxhash-dev liblz4-dev libzstd-dev libacl1-dev \ liblzma-dev libb2-dev ca-certificates fi echo "[INFO] Creating Python venv at ${VENV_DIR} ..." rm -rf "${VENV_DIR}" python3 -m venv "${VENV_DIR}" source "${VENV_DIR}/bin/activate" echo "[INFO] Upgrading pip/setuptools/wheel and installing build helpers..." python -m pip install -U "pip<25" "setuptools<70" wheel "Cython==0.29.36" pkgconfig "setuptools-scm<8" echo "[INFO] Cloning Borg ${BORG_TAG} sources into ${SRC_DIR} ..." rm -rf "${SRC_DIR}" git clone --depth 1 --branch "${BORG_TAG}" https://github.com/borgbackup/borg.git "${SRC_DIR}" export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig" export BORG_CYTHONIZE=1 export BORG_OPENSSL_PREFIX="/usr" export BORG_LIBXXHASH_PREFIX="/usr" export BORG_LIBLZ4_PREFIX="/usr" export BORG_LIBZSTD_PREFIX="/usr" export BORG_LIBB2_PREFIX="/usr" export BORG_LIBLZMA_PREFIX="/usr" export BORG_LIBACL_PREFIX="/usr" echo "[INFO] Removing any existing borg from venv (if present)..." python -m pip uninstall -y borgbackup || true rm -rf "${VENV_DIR}/lib/python3."*/site-packages/borg \ "${VENV_DIR}/lib/python3."*/site-packages/borgbackup-"*.dist-info" \ "${VENV_DIR}/lib/python3."*/site-packages/borg*.egg-info \ "${VENV_DIR}/lib/python3."*/site-packages/borg*.pth \ "${VENV_DIR}/lib/python3."*/site-packages/borg*.egg-link || true echo "[INFO] Building & installing Borg from source (non-editable)..." cd "${SRC_DIR}" python -m pip install --no-build-isolation --no-cache-dir . echo "[INFO] Import test for borg (should show version ${BORG_TAG})..." cd / python - <<'PY' import borg, sys, inspect print("borg", borg.__version__, "python", sys.version.split()[0]) print("from:", inspect.getsourcefile(borg) or borg.__file__) PY echo "[INFO] Creating entry stub..." cat > "${VENV_DIR}/borg2_entry.py" <<'EOF' import os, sys, types os.environ.setdefault("BORG_SELFTEST", "disabled") m = types.ModuleType("borg.selftest") def _selftest(*a, **kw): return 0 m.selftest = _selftest sys.modules["borg.selftest"] = m ver = types.ModuleType("borg._version") ver.version = "2.0.0b5" sys.modules["borg._version"] = ver import borg.archiver as A if __name__ == "__main__": A.main() EOF echo "[INFO] Building one-file binary with PyInstaller (no FUSE)..." python -m pip install "pyinstaller>=6,<7" cd "${VENV_DIR}" python -m PyInstaller -F -n "${BIN_NAME}" -c borg2_entry.py \ --collect-data borg \ --collect-binaries borg \ --exclude-module borg.testsuite \ --hidden-import=packaging.version \ --hidden-import=packaging.specifiers \ --clean -y echo "[INFO] Build complete. Binary:" echo " ${VENV_DIR}/dist/${BIN_NAME}" ls -lh "${VENV_DIR}/dist/${BIN_NAME}" || true