Files
juc500/dist-offline/juc500-offline-update-20260720-174241/start.sh
T
2026-07-21 21:04:25 +09:00

156 lines
4.8 KiB
Bash
Executable File

#!/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" "$@"