| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- #!/bin/bash
- # Vendoring script for hermes-chatto-plugin
- #
- # Downloads chattolib and all its dependencies with uv and vendors them into
- # vendor/. Three of them (pyqwest, protobuf, protobuf-py-ext) ship compiled
- # extension modules, so the tree is split by platform:
- #
- # vendor/common/ pure-Python packages, shared
- # vendor/platform/<tag>/ compiled extensions, one dir per platform
- #
- # vendor_path.py picks the right directory at import time.
- #
- # Usage:
- # ./vendor_chattolib.sh # all default platforms
- # PLATFORMS="linux-x86_64" ./vendor_chattolib.sh
- # CHATTOLIB_SPEC="chattolib==0.4.20" ./vendor_chattolib.sh
- # VENDOR_DIR="/tmp/vendor-alt" ./vendor_chattolib.sh
- set -euo pipefail
- PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
- # Overridable from the environment; unset or empty falls back to the plugin's
- # own vendor/ so neither `set -u` nor a stray empty value can break startup.
- VENDOR_DIR="${VENDOR_DIR:-$PLUGIN_DIR/vendor}"
- BUILD_DIR="$(mktemp -d)"
- trap 'rm -rf "$BUILD_DIR"' EXIT
- CHATTOLIB_SPEC="${CHATTOLIB_SPEC:-chattolib>=0.4.20}"
- # Wheels are resolved for this Python version. 3.11 is the project's minimum
- # (pyproject: requires-python) AND the version for which the binary packages
- # still provide cp310-abi3 wheels — those are forward compatible, so one build
- # covers 3.11, 3.12, 3.13 and 3.14. Do not raise this without checking that
- # the resulting .so files are still abi3.
- PYTHON_VERSION="${PYTHON_VERSION:-3.11}"
- # Platform tag (as used in vendor/platform/ and by vendor_path.py) mapped to
- # the uv --python-platform target. Add entries here to support more platforms;
- # vendor_path.py derives the same tags from platform.system()/machine().
- platform_target() {
- case "$1" in
- linux-x86_64) echo "x86_64-unknown-linux-gnu" ;;
- linux-aarch64) echo "aarch64-unknown-linux-gnu" ;;
- linux-x86_64-musl) echo "x86_64-unknown-linux-musl" ;;
- linux-aarch64-musl) echo "aarch64-unknown-linux-musl" ;;
- macos-arm64) echo "aarch64-apple-darwin" ;;
- macos-x86_64) echo "x86_64-apple-darwin" ;;
- windows-amd64) echo "x86_64-pc-windows-msvc" ;;
- *) return 1 ;;
- esac
- }
- # Default set: Linux (deployment, both architectures) and Apple Silicon (dev).
- DEFAULT_PLATFORMS="linux-x86_64 linux-aarch64 macos-arm64"
- read -r -a PLATFORM_LIST <<< "${PLATFORMS:-$DEFAULT_PLATFORMS}"
- if ! command -v uv > /dev/null 2>&1; then
- echo "❌ uv nicht gefunden — siehe https://docs.astral.sh/uv/" >&2
- exit 1
- fi
- echo "📦 Vendoring '$CHATTOLIB_SPEC' für: ${PLATFORM_LIST[*]}"
- echo " (Python $PYTHON_VERSION, nur Binär-Wheels — kein Bauen aus Sourcen)"
- for tag in "${PLATFORM_LIST[@]}"; do
- if ! target="$(platform_target "$tag")"; then
- echo "❌ Unbekannte Plattform '$tag'. Bekannt: linux-x86_64, linux-aarch64," >&2
- echo " linux-x86_64-musl, linux-aarch64-musl, macos-arm64, macos-x86_64, windows-amd64" >&2
- exit 1
- fi
- echo " → $tag ($target)"
- # --only-binary :all: is required: a source distribution could not be built
- # for a foreign platform, and building it for the host would silently
- # produce artifacts for the wrong architecture.
- uv pip install \
- --target "$BUILD_DIR/$tag" \
- --python-platform "$target" \
- --python-version "$PYTHON_VERSION" \
- --only-binary :all: \
- --quiet \
- "$CHATTOLIB_SPEC"
- done
- echo "🧹 Bereinige alten vendor-Ordner..."
- # Guard before the destructive step: this script must never run rm -rf with
- # an empty or unset target, whatever future edits do to the assignment above.
- : "${VENDOR_DIR:?VENDOR_DIR ist nicht gesetzt — Abbruch vor rm -rf}"
- rm -rf "$VENDOR_DIR"
- mkdir -p "$VENDOR_DIR"
- echo "✂️ Trenne plattformunabhängige von binären Paketen..."
- python3 "$PLUGIN_DIR/vendor_split.py" "$BUILD_DIR" "$VENDOR_DIR" "${PLATFORM_LIST[@]}"
- echo "📄 Erstelle __init__.py Marker..."
- touch "$VENDOR_DIR/__init__.py"
- find "$VENDOR_DIR" -type d -name "__pycache__" -exec rm -rf {} + 2> /dev/null || true
- echo "🔍 Verifiziere Import für die aktuelle Plattform..."
- if python3 -c "
- import sys
- sys.path.insert(0, '$PLUGIN_DIR')
- from vendor_path import setup_vendor_path, platform_tag
- try:
- setup_vendor_path()
- except ImportError as exc:
- print(f' ⓘ {exc}')
- sys.exit(0)
- import chattolib.client
- print(f' ✓ chattolib importiert ({platform_tag()})')
- "; then
- :
- else
- echo "❌ Import-Verifikation fehlgeschlagen" >&2
- exit 1
- fi
- echo "✓ Fertig: $(du -sh "$VENDOR_DIR" | cut -f1) in $VENDOR_DIR"
- echo " 'git add vendor/' nicht vergessen."
|