visionA/local-tool/Makefile
jim800121chen 071964bddd fix(local-tool): Windows build 跨平台相容性修正
Makefile:
- vendor-wheels-windows 自動偵測 pip3/pip/python -m pip,MSYS2 bash 裡沒 pip3 也能跑
- vendor-ffmpeg-windows 改用 python zipfile 解壓,移除 unzip 依賴
- 新增 build-server-windows / build-server-linux 兩個 cross-build target
- payload-windows / payload-linux 改依賴對應的 build-server-*,不再只印警告

bootstrap-windows.ps1:
- 設定 MSYS2_PATH_TYPE=inherit,讓 MSYS2 bash 繼承 Windows PATH 找到 go/pnpm/python/wails

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 01:58:25 +08:00

502 lines
25 KiB
Makefile
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# visionA-local — Makefile骨架M1-1
#
# 這份 Makefile 目前所有 targets 都只是 placeholder實際內容會在後續任務逐步填入
# - M1-2 複製 server core
# - M1-4 複製 frontend
# - M1-8 build-server / build-frontend 實作
# - M1-9 visiona-local (Wails) shell
# - M1-11 payload-macos
# - M1-12 installer-macos (dmg)
# - M2+ Windows / Linux / CI
#
# 詳見 .autoflow/04-architecture/build-pipeline.md
SHELL := /bin/bash
VERSION ?= v0.1.0-dev
BUILD_TIME := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
OS := $(shell uname -s | tr A-Z a-z)
DIST := dist
PAYLOAD := visiona-local/payload
.PHONY: help \
vendor-sync vendor-python vendor-wheels vendor-ffmpeg vendor-ytdlp \
vendor-python-windows vendor-wheels-windows vendor-ffmpeg-windows vendor-ytdlp-windows \
vendor-python-linux vendor-wheels-linux vendor-ffmpeg-linux vendor-ytdlp-linux \
server build-server \
frontend build-frontend build-embed \
payload payload-macos payload-windows payload-linux \
stage-macos stage-windows \
wails-macos wails-windows wails-linux \
dmg exe appimage \
dev dev-mock test lint fmt clean
# ── 幫助 ───────────────────────────────────────────────────────────
help: ## 列出所有 make targets
@echo "visionA-local — available targets (M1-1 skeleton)"
@echo ""
@echo " 依賴同步:"
@echo " vendor-sync 下載 python-build-standalone / wheels / ffmpeg / yt-dlp → vendor/"
@echo ""
@echo " Build單元"
@echo " server build Go server binary (→ dist/visiona-local-server)"
@echo " frontend pnpm build Next.js 靜態產物 (→ frontend/out)"
@echo ""
@echo " Payload 準備:"
@echo " payload-macos stage macOS payload → visiona-local/payload/"
@echo " payload-windows stage Windows payload"
@echo " payload-linux stage Linux payload"
@echo ""
@echo " Wails 應用 build"
@echo " wails-macos wails build darwin/amd64"
@echo " wails-windows wails build windows/amd64"
@echo " wails-linux wails build linux/amd64"
@echo ""
@echo " 安裝檔打包:"
@echo " dmg macOS .dmgdmgbuild"
@echo " exe Windows .exeInno Setup"
@echo " appimage Linux .AppImage"
@echo ""
@echo " 工具:"
@echo " clean 清除 dist/ payload/"
@echo ""
@echo "Note: 目前所有 target 都是 placeholder只印 TODO尚未實作。"
# ── 依賴同步 ───────────────────────────────────────────────────────
PYTHON_VERSION := 3.12.9
PBS_RELEASE := 20250317
PBS_URL_DARWIN := https://github.com/astral-sh/python-build-standalone/releases/download/$(PBS_RELEASE)/cpython-$(PYTHON_VERSION)+$(PBS_RELEASE)-x86_64-apple-darwin-install_only.tar.gz
FFMPEG_URL_DARWIN := https://evermeet.cx/ffmpeg/getrelease/ffmpeg/zip
YTDLP_URL_DARWIN := https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos
vendor-sync: vendor-python vendor-wheels vendor-ffmpeg vendor-ytdlp ## 下載所有第三方依賴到 vendor/(不進 git第三輪決策 Q-D=D2
@echo "==> vendor-sync 完成"
vendor-python: ## 下載 python-build-standalone tarball → vendor/python/darwin/
@mkdir -p vendor/python/darwin
@if [ ! -f vendor/python/darwin/python.tar.gz ]; then \
echo "==> 下載 python-build-standalone $(PYTHON_VERSION)+$(PBS_RELEASE) (macOS x86_64 install_only)..."; \
curl -fL -o vendor/python/darwin/python.tar.gz "$(PBS_URL_DARWIN)"; \
echo "==> tarball 大小:$$(du -sh vendor/python/darwin/python.tar.gz | cut -f1)"; \
else \
echo "==> python tarball 已存在,跳過下載 ($$(du -sh vendor/python/darwin/python.tar.gz | cut -f1))"; \
fi
vendor-wheels: ## 同步 wheels → vendor/wheels/darwin/(內部 wheel 從 visiona-local/wheels 複製,公開相依用 pip download
@mkdir -p vendor/wheels/darwin
@echo "==> 同步內部 wheelsKneronPLUS 等)..."
@if [ -d visiona-local/wheels/macos ]; then \
cp visiona-local/wheels/macos/*.whl vendor/wheels/darwin/ 2>/dev/null || true; \
fi
@echo "==> 從 PyPI 下載公開相依 wheels (cp312, macosx_x86_64)..."
@pip3 download \
--only-binary=:all: \
--platform macosx_10_9_x86_64 \
--platform macosx_11_0_x86_64 \
--platform macosx_12_0_x86_64 \
--python-version 3.12 \
--implementation cp \
--dest vendor/wheels/darwin \
numpy opencv-python-headless pyusb requests || echo "WARN: pip download 部分失敗(詳見上方訊息)"
@echo "==> wheels 總覽:"
@ls -1 vendor/wheels/darwin/*.whl 2>/dev/null | wc -l | xargs -I{} echo " 共 {} 個 wheel"
@du -sh vendor/wheels/darwin
vendor-ffmpeg: ## 下載 ffmpeg static build (macOS x86_64) → vendor/ffmpeg/darwin/(預設要求 LGPL必要時可用 VISIONA_ALLOW_GPL_FFMPEG=1 暫時放行 GPL
@mkdir -p vendor/ffmpeg/darwin
@if [ -f vendor/ffmpeg/darwin/ffmpeg ]; then \
echo "==> ffmpeg 已存在,跳過 ($$(du -sh vendor/ffmpeg/darwin/ffmpeg | cut -f1))"; \
else \
echo "==> 下載 ffmpeg static build (macOS) from evermeet.cx..."; \
curl -fL -o /tmp/ffmpeg-latest.zip "$(FFMPEG_URL_DARWIN)"; \
unzip -o /tmp/ffmpeg-latest.zip -d vendor/ffmpeg/darwin/; \
rm -f /tmp/ffmpeg-latest.zip; \
chmod +x vendor/ffmpeg/darwin/ffmpeg; \
echo "==> ffmpeg 大小:$$(du -sh vendor/ffmpeg/darwin/ffmpeg | cut -f1)"; \
vendor/ffmpeg/darwin/ffmpeg -version 2>&1 | head -3; \
echo "==> 授權檢查:"; \
if vendor/ffmpeg/darwin/ffmpeg -version 2>&1 | grep -q -- '--enable-gpl'; then \
if [ "$${VISIONA_ALLOW_GPL_FFMPEG:-0}" = "1" ]; then \
echo " !! WARNING: 此 build 含 --enable-gplGPL build !!"; \
echo " !! VISIONA_ALLOW_GPL_FFMPEG=1 已啟用,暫時允許(僅限本地驗收,不可發佈) !!"; \
else \
echo "!! 錯誤:此 build 含 --enable-gpl違反 LGPL 策略 !!"; \
echo "!! macOS 暫無現成 LGPL binary 來源,需自行 build 或用 VISIONA_ALLOW_GPL_FFMPEG=1 暫時放行 !!"; \
rm -f vendor/ffmpeg/darwin/ffmpeg; \
exit 1; \
fi; \
else \
echo " OK: 未偵測到 --enable-gpl"; \
fi; \
fi
vendor-ytdlp: ## 下載 yt-dlp standalone (macOS) → vendor/yt-dlp/darwin/
@mkdir -p vendor/yt-dlp/darwin
@if [ ! -f vendor/yt-dlp/darwin/yt-dlp ]; then \
echo "==> 下載 yt-dlp (macOS)..."; \
curl -fL -o vendor/yt-dlp/darwin/yt-dlp "$(YTDLP_URL_DARWIN)"; \
chmod +x vendor/yt-dlp/darwin/yt-dlp; \
echo "==> yt-dlp 大小:$$(du -sh vendor/yt-dlp/darwin/yt-dlp | cut -f1)"; \
vendor/yt-dlp/darwin/yt-dlp --version 2>&1 | head -1; \
else \
echo "==> yt-dlp 已存在,跳過 ($$(du -sh vendor/yt-dlp/darwin/yt-dlp | cut -f1))"; \
fi
# ── Build單元 ──────────────────────────────────────────────────
server: build-server ## alias for build-server
build-server: build-embed ## build Go server binary → dist/visiona-local-server會先 build frontend + embed
@mkdir -p $(DIST)
cd server && go build -o ../$(DIST)/visiona-local-server .
@echo "built: $(DIST)/visiona-local-server"
build-server-windows: build-embed ## 交叉/原生 build Windows server → payload/windows/bin/visiona-local-server.exe
@mkdir -p payload/windows/bin
cd server && GOOS=windows GOARCH=amd64 go build -o ../payload/windows/bin/visiona-local-server.exe .
@echo "built: payload/windows/bin/visiona-local-server.exe"
build-server-linux: build-embed ## 交叉/原生 build Linux server → payload/linux/bin/visiona-local-server
@mkdir -p payload/linux/bin
cd server && GOOS=linux GOARCH=amd64 go build -o ../payload/linux/bin/visiona-local-server .
@echo "built: payload/linux/bin/visiona-local-server"
frontend: build-frontend ## alias for build-frontend
build-frontend: ## pnpm build → frontend/out/
@echo "==> pnpm build frontend..."
cd frontend && pnpm install --frozen-lockfile && pnpm build
@echo "==> frontend/out 完成:"
@du -sh frontend/out
build-embed: build-frontend ## 同步 frontend/out → server/web/out 供 go:embed
@echo "==> 同步 frontend/out → server/web/out..."
rm -rf server/web/out
mkdir -p server/web/out
cp -R frontend/out/. server/web/out/
@du -sh server/web/out
# ── Payload 準備 ───────────────────────────────────────────────────
payload: payload-$(OS) ## 依當前 OS 準備 payload
payload-macos: build-server vendor-python vendor-wheels vendor-ffmpeg vendor-ytdlp ## 準備 macOS payload → payload/darwin/(含 python runtime + wheels + ffmpeg + yt-dlp
@echo "==> 建立 macOS payload (binary + models + scripts + python + wheels + ffmpeg + yt-dlp)..."
rm -rf payload/darwin
mkdir -p payload/darwin/bin payload/darwin/data payload/darwin/scripts payload/darwin/python payload/darwin/wheels
cp dist/visiona-local-server payload/darwin/bin/
cp vendor/ffmpeg/darwin/ffmpeg payload/darwin/bin/
cp vendor/yt-dlp/darwin/yt-dlp payload/darwin/bin/
chmod +x payload/darwin/bin/ffmpeg payload/darwin/bin/yt-dlp
cp -R server/data/* payload/darwin/data/
cp -R server/scripts/* payload/darwin/scripts/
cp vendor/python/darwin/python.tar.gz payload/darwin/python/
@cp vendor/wheels/darwin/*.whl payload/darwin/wheels/ 2>/dev/null || true
@echo "==> macOS payload 完成:"
@du -sh payload/darwin
@echo ""
@echo "payload/darwin 結構:"
@find payload/darwin -maxdepth 2 -type d | sed 's|^| |'
@echo ""
@echo "payload/darwin/python"
@ls -lh payload/darwin/python
@echo "payload/darwin/wheels"
@ls -1 payload/darwin/wheels | head -20
stage-macos: payload-macos ## 將 payload/darwin/ 放到 Wails build/darwin/Resources/
@echo "==> 放置 payload 到 Wails build/darwin/Resources..."
rm -rf visiona-local/build/darwin/Resources
mkdir -p visiona-local/build/darwin/Resources
cp -R payload/darwin/. visiona-local/build/darwin/Resources/
@echo "==> stage 完成:"
@du -sh visiona-local/build/darwin/Resources
# ── M4Windows vendor + payload + wails + exe ─────────────────────
# 注意wails-windows 與 exe 必須在 Windows runner 上跑;在 macOS 上會明確 fail。
# payload-windows / vendor-*-windows 是 curl 下載跨平台可跑server.exe 步驟除外)。
PBS_URL_WINDOWS := https://github.com/astral-sh/python-build-standalone/releases/download/$(PBS_RELEASE)/cpython-$(PYTHON_VERSION)+$(PBS_RELEASE)-x86_64-pc-windows-msvc-install_only.tar.gz
FFMPEG_URL_WINDOWS := https://github.com/BtbN/FFmpeg-Builds/releases/latest/download/ffmpeg-master-latest-win64-gpl.zip
YTDLP_URL_WINDOWS := https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe
vendor-python-windows: ## 下載 python-build-standalone Windows x86_64 → vendor/python/windows/
@mkdir -p vendor/python/windows
@if [ ! -f vendor/python/windows/python.tar.gz ]; then \
echo "==> 下載 python-build-standalone $(PYTHON_VERSION)+$(PBS_RELEASE) (Windows x86_64 install_only)..."; \
curl -fL -o vendor/python/windows/python.tar.gz "$(PBS_URL_WINDOWS)"; \
echo "==> tarball 大小:$$(du -sh vendor/python/windows/python.tar.gz | cut -f1)"; \
else \
echo "==> python (Windows) tarball 已存在,跳過 ($$(du -sh vendor/python/windows/python.tar.gz | cut -f1))"; \
fi
vendor-wheels-windows: ## 同步 Windows wheels → vendor/wheels/windows/
@mkdir -p vendor/wheels/windows
@echo "==> 同步內部 wheels (Windows, KneronPLUS 等)..."
@if [ -d visiona-local/wheels/windows ]; then \
cp visiona-local/wheels/windows/*.whl vendor/wheels/windows/ 2>/dev/null || true; \
fi
@echo "==> 從 PyPI 下載公開相依 wheels (cp312, win_amd64)..."
@PIP_CMD=$$(command -v pip3 || command -v pip); \
if [ -z "$$PIP_CMD" ]; then \
PY=$$(command -v python3 || command -v python || command -v py); \
if [ -n "$$PY" ]; then PIP_CMD="$$PY -m pip"; fi; \
fi; \
if [ -z "$$PIP_CMD" ]; then \
echo "WARN: 找不到 pip / python跳過 PyPI 下載(僅使用內部 wheels"; \
else \
echo "==> 使用 $$PIP_CMD"; \
$$PIP_CMD download \
--only-binary=:all: \
--platform win_amd64 \
--python-version 3.12 \
--implementation cp \
--dest vendor/wheels/windows \
numpy opencv-python-headless pyusb requests || echo "WARN: pip download 部分失敗(詳見上方訊息)"; \
fi
@echo "==> Windows wheels 總覽:"
@ls -1 vendor/wheels/windows/*.whl 2>/dev/null | wc -l | xargs -I{} echo " 共 {} 個 wheel"
@du -sh vendor/wheels/windows 2>/dev/null || true
vendor-ffmpeg-windows: ## 下載 ffmpeg Windows static build → vendor/ffmpeg/windows/
@mkdir -p vendor/ffmpeg/windows
@if [ -f vendor/ffmpeg/windows/ffmpeg.exe ]; then \
echo "==> ffmpeg.exe 已存在,跳過"; \
else \
echo "==> 下載 ffmpeg Windows build from BtbN..."; \
echo "!! WARNING: BtbN 為 GPL buildlicense 由 PM 最終確認 !!"; \
curl -fL -o /tmp/ffmpeg-win.zip "$(FFMPEG_URL_WINDOWS)"; \
PY=$$(command -v python3 || command -v python || command -v py); \
if [ -z "$$PY" ]; then echo "ERROR: 需要 python 來解壓 zip"; exit 1; fi; \
$$PY -c "import zipfile, os, shutil; z=zipfile.ZipFile('/tmp/ffmpeg-win.zip'); \
members=[n for n in z.namelist() if n.endswith('/bin/ffmpeg.exe')]; \
assert members, 'ffmpeg.exe not found in zip'; \
src=z.open(members[0]); dst=open('vendor/ffmpeg/windows/ffmpeg.exe','wb'); \
shutil.copyfileobj(src, dst); src.close(); dst.close(); z.close()"; \
rm -f /tmp/ffmpeg-win.zip; \
echo "==> ffmpeg.exe 大小:$$(du -sh vendor/ffmpeg/windows/ffmpeg.exe | cut -f1)"; \
fi
vendor-ytdlp-windows: ## 下載 yt-dlp.exe → vendor/yt-dlp/windows/
@mkdir -p vendor/yt-dlp/windows
@if [ ! -f vendor/yt-dlp/windows/yt-dlp.exe ]; then \
echo "==> 下載 yt-dlp.exe..."; \
curl -fL -o vendor/yt-dlp/windows/yt-dlp.exe "$(YTDLP_URL_WINDOWS)"; \
echo "==> yt-dlp.exe 大小:$$(du -sh vendor/yt-dlp/windows/yt-dlp.exe | cut -f1)"; \
else \
echo "==> yt-dlp.exe 已存在,跳過"; \
fi
payload-windows: build-server-windows vendor-python-windows vendor-wheels-windows vendor-ffmpeg-windows vendor-ytdlp-windows ## 準備 Windows payload → payload/windows/
@echo "==> 建立 Windows payload (binary + models + scripts + python + wheels + ffmpeg + yt-dlp)..."
@# 注意:不 rm -rf payload/windows因為 build-server-windows 已先把 .exe 放進去
mkdir -p payload/windows/bin payload/windows/data payload/windows/scripts payload/windows/python payload/windows/wheels
@if [ ! -f payload/windows/bin/visiona-local-server.exe ]; then \
echo "!! ERROR: payload/windows/bin/visiona-local-server.exe 不存在build-server-windows 可能失敗 !!"; \
exit 1; \
fi
cp vendor/ffmpeg/windows/ffmpeg.exe payload/windows/bin/
cp vendor/yt-dlp/windows/yt-dlp.exe payload/windows/bin/
cp -R server/data/. payload/windows/data/
cp -R server/scripts/. payload/windows/scripts/
cp vendor/python/windows/python.tar.gz payload/windows/python/
@cp vendor/wheels/windows/*.whl payload/windows/wheels/ 2>/dev/null || true
@echo "==> Windows payload 完成:"
@du -sh payload/windows
@echo ""
@echo "payload/windows 結構:"
@find payload/windows -maxdepth 2 -type d | sed 's|^| |'
stage-windows: payload-windows ## 將 payload/windows/ 放到 Wails build/windows/Resources/
@echo "==> 放置 payload 到 Wails build/windows/Resources..."
rm -rf visiona-local/build/windows/Resources
mkdir -p visiona-local/build/windows/Resources
cp -R payload/windows/. visiona-local/build/windows/Resources/
@echo "==> stage 完成:"
@du -sh visiona-local/build/windows/Resources
# ── M5Linux vendor + payload + wails + AppImage ──────────────────
# 注意wails-linux 與 appimage 必須在 Linux runner 上跑;在 macOS 上會明確 fail。
# payload-linux / vendor-*-linux 是 curl 下載跨平台可跑server 步驟除外)。
PBS_URL_LINUX := https://github.com/astral-sh/python-build-standalone/releases/download/$(PBS_RELEASE)/cpython-$(PYTHON_VERSION)+$(PBS_RELEASE)-x86_64-unknown-linux-gnu-install_only.tar.gz
FFMPEG_URL_LINUX := https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
YTDLP_URL_LINUX := https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux
vendor-python-linux: ## 下載 python-build-standalone Linux x86_64 → vendor/python/linux/
@mkdir -p vendor/python/linux
@if [ ! -f vendor/python/linux/python.tar.gz ]; then \
echo "==> 下載 python-build-standalone $(PYTHON_VERSION)+$(PBS_RELEASE) (Linux x86_64 install_only)..."; \
curl -fL -o vendor/python/linux/python.tar.gz "$(PBS_URL_LINUX)"; \
echo "==> tarball 大小:$$(du -sh vendor/python/linux/python.tar.gz | cut -f1)"; \
else \
echo "==> python (Linux) tarball 已存在,跳過 ($$(du -sh vendor/python/linux/python.tar.gz | cut -f1))"; \
fi
vendor-wheels-linux: ## 同步 Linux wheels → vendor/wheels/linux/
@mkdir -p vendor/wheels/linux
@echo "==> 同步內部 wheels (Linux, KneronPLUS 等)..."
@if [ -d visiona-local/wheels/linux ]; then \
cp visiona-local/wheels/linux/*.whl vendor/wheels/linux/ 2>/dev/null || true; \
fi
@echo "==> 從 PyPI 下載公開相依 wheels (cp312, manylinux2014_x86_64)..."
@pip3 download \
--only-binary=:all: \
--platform manylinux2014_x86_64 \
--python-version 3.12 \
--implementation cp \
--dest vendor/wheels/linux \
numpy opencv-python-headless pyusb requests || echo "WARN: pip download 部分失敗(詳見上方訊息)"
@echo "==> Linux wheels 總覽:"
@ls -1 vendor/wheels/linux/*.whl 2>/dev/null | wc -l | xargs -I{} echo " 共 {} 個 wheel"
@du -sh vendor/wheels/linux 2>/dev/null || true
vendor-ffmpeg-linux: ## 下載 ffmpeg Linux static build → vendor/ffmpeg/linux/
@mkdir -p vendor/ffmpeg/linux
@if [ -f vendor/ffmpeg/linux/ffmpeg ]; then \
echo "==> ffmpeg (Linux) 已存在,跳過 ($$(du -sh vendor/ffmpeg/linux/ffmpeg | cut -f1))"; \
else \
echo "==> 下載 ffmpeg static build (Linux x86_64) from johnvansickle..."; \
echo "!! WARNING: johnvansickle build 為 GPL build正式發佈前需改用 LGPL 來源 !!"; \
curl -fL -o /tmp/ffmpeg-linux.tar.xz "$(FFMPEG_URL_LINUX)"; \
mkdir -p /tmp/ffmpeg-linux-extract; \
tar xf /tmp/ffmpeg-linux.tar.xz -C /tmp/ffmpeg-linux-extract --strip-components=1; \
cp /tmp/ffmpeg-linux-extract/ffmpeg vendor/ffmpeg/linux/; \
chmod +x vendor/ffmpeg/linux/ffmpeg; \
rm -rf /tmp/ffmpeg-linux* ; \
echo "==> ffmpeg (Linux) 大小:$$(du -sh vendor/ffmpeg/linux/ffmpeg | cut -f1)"; \
if [ "$${VISIONA_ALLOW_GPL_FFMPEG:-0}" != "1" ]; then \
echo " ⚠️ 提醒:此 build 為 GPL僅限本地驗收發佈前請改用 LGPL build"; \
fi; \
fi
vendor-ytdlp-linux: ## 下載 yt-dlp (Linux) → vendor/yt-dlp/linux/
@mkdir -p vendor/yt-dlp/linux
@if [ ! -f vendor/yt-dlp/linux/yt-dlp ]; then \
echo "==> 下載 yt-dlp (Linux)..."; \
curl -fL -o vendor/yt-dlp/linux/yt-dlp "$(YTDLP_URL_LINUX)"; \
chmod +x vendor/yt-dlp/linux/yt-dlp; \
echo "==> yt-dlp (Linux) 大小:$$(du -sh vendor/yt-dlp/linux/yt-dlp | cut -f1)"; \
else \
echo "==> yt-dlp (Linux) 已存在,跳過"; \
fi
payload-linux: build-server-linux vendor-python-linux vendor-wheels-linux vendor-ffmpeg-linux vendor-ytdlp-linux ## 準備 Linux payload → payload/linux/
@echo "==> 建立 Linux payload (binary + models + scripts + python + wheels + ffmpeg + yt-dlp)..."
mkdir -p payload/linux/bin payload/linux/data payload/linux/scripts payload/linux/python payload/linux/wheels
@if [ ! -f payload/linux/bin/visiona-local-server ]; then \
echo "!! ERROR: payload/linux/bin/visiona-local-server 不存在build-server-linux 可能失敗 !!"; \
exit 1; \
fi
@chmod +x payload/linux/bin/visiona-local-server
@cp vendor/ffmpeg/linux/ffmpeg payload/linux/bin/ 2>/dev/null && chmod +x payload/linux/bin/ffmpeg || echo "!! WARN: ffmpeg 缺失"
@cp vendor/yt-dlp/linux/yt-dlp payload/linux/bin/ 2>/dev/null && chmod +x payload/linux/bin/yt-dlp || echo "!! WARN: yt-dlp 缺失"
@if [ -d server/data ]; then cp -R server/data/. payload/linux/data/; fi
@if [ -d server/scripts ]; then cp -R server/scripts/. payload/linux/scripts/; fi
@cp vendor/python/linux/python.tar.gz payload/linux/python/ 2>/dev/null || echo "!! WARN: python tarball 缺失"
@cp vendor/wheels/linux/*.whl payload/linux/wheels/ 2>/dev/null || true
@echo "==> Linux payload 完成:"
@du -sh payload/linux 2>/dev/null || true
@echo ""
@echo "payload/linux 結構:"
@find payload/linux -maxdepth 2 -type d 2>/dev/null | sed 's|^| |'
# ── Wails build ────────────────────────────────────────────────────
wails-macos: stage-macos ## wails build darwin/amd64 → visiona-local/build/bin/visiona-local.app
cd visiona-local && wails build -platform darwin/amd64 -clean
cp -R visiona-local/build/darwin/Resources/bin \
visiona-local/build/darwin/Resources/data \
visiona-local/build/darwin/Resources/scripts \
visiona-local/build/darwin/Resources/python \
visiona-local/build/darwin/Resources/wheels \
visiona-local/build/bin/visiona-local.app/Contents/Resources/
codesign --force --deep --sign - visiona-local/build/bin/visiona-local.app
codesign --verify --verbose visiona-local/build/bin/visiona-local.app
@du -sh visiona-local/build/bin/visiona-local.app
wails-windows: stage-windows ## ⚠️ 必須在 Windows runner 上執行wails build -platform windows/amd64
@case "$$(uname -s 2>/dev/null)" in \
MINGW*|CYGWIN*|MSYS*) : ;; \
*) \
echo ""; \
echo "❌ wails-windows 只能在 Windows runner 上 build偵測到 $$(uname -s)"; \
echo " 請在 Windows 機器上執行此 target或用 CI 的 Windows runner"; \
echo " 若只是要檢查前置步驟,可單獨跑 make stage-windows"; \
echo ""; \
exit 1 ;; \
esac
cd visiona-local && wails build -platform windows/amd64 -clean
@du -sh visiona-local/build/bin/visiona-local.exe
wails-linux: payload-linux ## ⚠️ 必須在 Linux runner 上執行wails build -platform linux/amd64
@if [ "$$(uname -s)" != "Linux" ]; then \
echo ""; \
echo "❌ wails-linux 只能在 Linux 上 build偵測到 $$(uname -s)"; \
echo " 請在 Linux x86_64 runnerGitHub Actions ubuntu-latest 即可)執行"; \
echo " 若只是要檢查前置步驟,可單獨跑 make payload-linux"; \
echo ""; \
exit 1; \
fi
cd visiona-local && wails build -platform linux/amd64 -clean
@du -sh visiona-local/build/bin/visiona-local
# ── 安裝檔打包 ─────────────────────────────────────────────────────
dmg: wails-macos ## hdiutil UDZO → dist/visiona-local.dmg
mkdir -p $(DIST)
rm -f $(DIST)/visiona-local.dmg
hdiutil create -volname "visionA-local" \
-srcfolder visiona-local/build/bin/visiona-local.app \
-ov -format UDZO \
$(DIST)/visiona-local.dmg
@du -sh $(DIST)/visiona-local.dmg
@file $(DIST)/visiona-local.dmg
exe: wails-windows ## ⚠️ 必須在 Windows 上跑Inno Setup → dist/visiona-local-*-windows-x64.exe
@if ! command -v iscc > /dev/null 2>&1 && ! command -v iscc.exe > /dev/null 2>&1; then \
echo ""; \
echo "❌ Inno Setup Compiler (iscc) 未安裝"; \
echo " 請從 https://jrsoftware.org/isdl.php 下載並安裝 Inno Setup 6"; \
echo " 安裝後將 iscc.exe 目錄加入 PATH"; \
echo ""; \
exit 1; \
fi
@mkdir -p $(DIST)
iscc installer/windows/visiona-local.iss
@echo "==> 產出:"
@ls -lh $(DIST)/visiona-local-*-windows-x64.exe 2>/dev/null || echo "未找到產出檔"
appimage: wails-linux ## ⚠️ 必須在 Linux 上跑build-appimage.sh → dist/visiona-local-*-linux-x64.AppImage
@if [ "$$(uname -s)" != "Linux" ]; then \
echo ""; \
echo "❌ appimage 只能在 Linux 上 build偵測到 $$(uname -s)"; \
echo " 需要 appimagetool請在 Linux x86_64 runner 執行"; \
echo ""; \
exit 1; \
fi
@mkdir -p $(DIST)
VERSION=$(VERSION) bash installer/linux/build-appimage.sh
@echo "==> 產出:"
@ls -lh $(DIST)/visiona-local-*-linux-x64.AppImage 2>/dev/null || echo "未找到產出檔"
# ── 開發placeholder ────────────────────────────────────────────
dev:
@echo "TODO: make -j2 dev-server dev-frontend開發模式"
dev-mock:
@echo "TODO: make -j2 dev-mock-server dev-frontendMock 模式)"
test:
@echo "TODO: go test + pnpm test"
lint:
@echo "TODO: go vet + pnpm lint"
fmt:
@echo "TODO: go fmt"
# ── 清理 ───────────────────────────────────────────────────────────
clean: ## 清除 dist/ 與 payload/ 產物
@echo "Cleaning dist/ and payload artifacts..."
rm -rf $(DIST)
rm -rf $(PAYLOAD)
@mkdir -p $(DIST) $(PAYLOAD)
@touch $(DIST)/.gitkeep $(PAYLOAD)/.gitkeep
@echo "Done."