#!/usr/bin/env bash # JUC500 GUI 실행 (인자 없으면 GUI, 있으면 CLI로 전달) # macOS / Windows (Git Bash) 공통 set -euo pipefail ROOT="$(cd "$(dirname "$0")" && pwd)" cd "$ROOT" is_windows() { case "$(uname -s 2>/dev/null || echo unknown)" in MINGW*|MSYS*|CYGWIN*) return 0 ;; *) return 1 ;; esac } setup_hint() { if is_windows; then echo " scripts\\setup_windows.bat (또는 ./start_win.sh 재실행 — 자동 설정)" >&2 else echo " ./scripts/setup_macos.sh" >&2 fi } # Windows zip 복사 후: Mac .venv 제거 + vendor 로 .venv 자동 생성 if is_windows; then if [[ -f "$ROOT/scripts/bootstrap_windows.sh" ]]; then bash "$ROOT/scripts/bootstrap_windows.sh" || exit 1 fi fi # venv Python 선택 (Windows: Scripts\python.exe, Unix: bin/python) # 크로스 OS로 복사된 .venv 대비 — 현재 플랫폼에 맞는 인터프리터만 고른다. PY="" if is_windows && [[ -f "$ROOT/.venv/Scripts/python.exe" ]]; then PY="$ROOT/.venv/Scripts/python.exe" elif [[ -x "$ROOT/.venv/bin/python" ]] && "$ROOT/.venv/bin/python" -c "import sys" 2>/dev/null; then PY="$ROOT/.venv/bin/python" elif command -v python3 >/dev/null 2>&1; then PY="$(command -v python3)" elif command -v python >/dev/null 2>&1; then PY="$(command -v python)" else echo "Python 이 없습니다. 먼저 설치하세요:" >&2 setup_hint exit 1 fi if is_windows; then if [[ ! -f "$ROOT/.venv/Scripts/python.exe" ]]; then echo "경고: .venv 없음 — 시스템 Python 사용. 문제가 있으면:" >&2 setup_hint fi elif [[ ! -x "$ROOT/.venv/bin/python" ]]; then echo "경고: .venv 없음 — 시스템 Python 사용. 문제가 있으면:" >&2 setup_hint fi # Windows 네이티브 Python 은 PYTHONPATH 에 Win 경로·세미콜론을 기대 if is_windows; then WINROOT="" if command -v cygpath >/dev/null 2>&1; then WINROOT="$(cygpath -w "$ROOT")" elif WINROOT="$(cd "$ROOT" && pwd -W 2>/dev/null)" && [[ -n "$WINROOT" ]]; then : else # MSYS /c/dev/juc500 → C:/dev/juc500 (Windows python 호환) WINROOT="$ROOT" if [[ "$WINROOT" =~ ^/([a-zA-Z])/(.*)$ ]]; then WINROOT="${BASH_REMATCH[1]}:/${BASH_REMATCH[2]}" fi fi export PYTHONPATH="${WINROOT}${PYTHONPATH:+;$PYTHONPATH}" export JUC500_ROOT="${WINROOT}" else export PYTHONPATH="$ROOT${PYTHONPATH:+:$PYTHONPATH}" export JUC500_ROOT="$ROOT" fi # Windows: libusb DLL 은 python.exe 옆에 있어야 pyusb 가 로드함 if is_windows; then libusb_src="$ROOT/vendor/libusb-1.0.dll" py_dir="$(dirname "$PY")" libusb_dst="$py_dir/libusb-1.0.dll" if [[ -f "$libusb_src" ]]; then cp -f "$libusb_src" "$libusb_dst" 2>/dev/null || true echo "libusb-1.0.dll → $py_dir/" elif [[ ! -f "$libusb_dst" ]]; then echo "경고: vendor/libusb-1.0.dll 없음 — vendor/ 포함 zip 인지 확인하세요" >&2 fi fi # editable install 가 예전 경로(C:\dev\juc500\juc500)를 가리키면 구버전이 로드됨 — 매 기동 시 현재 ROOT 로 고정 if [[ -f "$ROOT/pyproject.toml" ]]; then pip_args=(-m pip install -e "$ROOT" --no-deps -q) if [[ -d "$ROOT/vendor/wheels" ]]; then pip_args+=(--no-index --find-links="$ROOT/vendor/wheels") fi "$PY" "${pip_args[@]}" 2>/dev/null || true fi # 의존성 빠른 확인 if ! "$PY" -c "import usb" 2>/dev/null; then echo "pyusb 가 없습니다. 먼저 설치하세요:" >&2 setup_hint exit 1 fi if is_windows; then libusb_ok="$( "$PY" -c " from juc500_xfer.usb_link import libusb_path p = libusb_path() print(p or '') import sys sys.exit(0 if p else 1) " 2>/dev/null || true )" if [[ -z "$libusb_ok" ]]; then echo "libusb-1.0 를 로드하지 못했습니다. Windows에서:" >&2 echo " scripts\\ensure_libusb_windows.bat" >&2 echo " 또는 scripts\\setup_windows.bat" >&2 exit 1 fi echo "libusb: $libusb_ok" fi # 기존 juc500 인스턴스가 IF5를 점유하면 Access denied 가 난다 — 먼저 종료 kill_msg="$( "$PY" -c " from juc500_xfer.wormhole_kill import kill_other_juc500_processes r = kill_other_juc500_processes(force=True) print(r.get('message') or '') " 2>/dev/null || true )" if [[ -n "${kill_msg}" ]]; then echo "$kill_msg" fi build_info="$( "$PY" -c " import juc500_xfer.usb_link as u print(getattr(u, 'XFER_BUILD', '?'), '|', u.__file__) " 2>/dev/null || echo "? | import failed" )" echo "JUC500 build: ${build_info}" # 개발 중: Python GUI 직접 실행. Tauri 케이블 감시는 JUC500_USE_TAURI=1 일 때만. if [[ "${JUC500_USE_TAURI:-0}" == "1" && -f "$ROOT/scripts/launch_tauri.sh" ]]; then TAURI_RELEASE="$ROOT/juc500-app/src-tauri/target/release/juc500-app" TAURI_DEBUG="$ROOT/juc500-app/src-tauri/target/debug/juc500-app" if [[ -x "$TAURI_RELEASE" || -x "$TAURI_DEBUG" ]]; then exec "$ROOT/scripts/launch_tauri.sh" fi fi exec "$PY" "$ROOT/juc500_app.py" "$@"