diff --git a/local-tool/Makefile b/local-tool/Makefile index ef1ef90..cf4c913 100644 --- a/local-tool/Makefile +++ b/local-tool/Makefile @@ -150,6 +150,16 @@ build-server: build-embed ## build Go server binary → dist/visiona-local-serve 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/ @@ -224,13 +234,23 @@ vendor-wheels-windows: ## 同步 Windows wheels → vendor/wheels/windows/ cp visiona-local/wheels/windows/*.whl vendor/wheels/windows/ 2>/dev/null || true; \ fi @echo "==> 從 PyPI 下載公開相依 wheels (cp312, win_amd64)..." - @pip3 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 部分失敗(詳見上方訊息)" + @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 @@ -243,7 +263,13 @@ vendor-ffmpeg-windows: ## 下載 ffmpeg Windows static build → vendor/ffmpeg/w echo "==> 下載 ffmpeg Windows build from BtbN..."; \ echo "!! WARNING: BtbN 為 GPL build;license 由 PM 最終確認 !!"; \ curl -fL -o /tmp/ffmpeg-win.zip "$(FFMPEG_URL_WINDOWS)"; \ - unzip -j -o /tmp/ffmpeg-win.zip "*/bin/ffmpeg.exe" -d vendor/ffmpeg/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 @@ -258,16 +284,13 @@ vendor-ytdlp-windows: ## 下載 yt-dlp.exe → vendor/yt-dlp/windows/ echo "==> yt-dlp.exe 已存在,跳過"; \ fi -payload-windows: vendor-python-windows vendor-wheels-windows vendor-ffmpeg-windows vendor-ytdlp-windows ## 準備 Windows payload → payload/windows/ +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 + @# 注意:不 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 - @echo "Note: visiona-local-server.exe 必須在 Windows runner 上 build:" - @echo " cd server && GOOS=windows GOARCH=amd64 go build -o ../payload/windows/bin/visiona-local-server.exe ." - @if [ -f payload/windows/bin/visiona-local-server.exe ]; then \ - echo "==> server.exe 已存在"; \ - else \ - echo "!! WARN: payload/windows/bin/visiona-local-server.exe 不存在(需在 Windows 上補 build) !!"; \ + @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/ @@ -355,21 +378,14 @@ vendor-ytdlp-linux: ## 下載 yt-dlp (Linux) → vendor/yt-dlp/linux/ echo "==> yt-dlp (Linux) 已存在,跳過"; \ fi -payload-linux: vendor-python-linux vendor-wheels-linux vendor-ffmpeg-linux vendor-ytdlp-linux ## 準備 Linux payload → payload/linux/ +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)..." - rm -rf payload/linux mkdir -p payload/linux/bin payload/linux/data payload/linux/scripts payload/linux/python payload/linux/wheels - @echo "Note: visiona-local-server (Linux) 必須在 Linux runner 上 build:" - @echo " cd server && GOOS=linux GOARCH=amd64 go build -o ../payload/linux/bin/visiona-local-server ." - @if [ -f payload/linux/bin/visiona-local-server ]; then \ - echo "==> visiona-local-server 已存在"; \ - elif [ -f dist/visiona-local-server-linux ]; then \ - cp dist/visiona-local-server-linux payload/linux/bin/visiona-local-server; \ - chmod +x payload/linux/bin/visiona-local-server; \ - echo "==> 從 dist/visiona-local-server-linux 複製 server binary"; \ - else \ - echo "!! WARN: payload/linux/bin/visiona-local-server 不存在(需在 Linux 上補 build) !!"; \ + @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 diff --git a/local-tool/scripts/bootstrap-windows.ps1 b/local-tool/scripts/bootstrap-windows.ps1 index 206d9f9..c19ef1f 100644 --- a/local-tool/scripts/bootstrap-windows.ps1 +++ b/local-tool/scripts/bootstrap-windows.ps1 @@ -70,7 +70,11 @@ if (-not (Test-Path 'C:\msys64\usr\bin\make.exe')) { Log "[4/4] 開始 build(target=$Target)" Log '⚠️ ffmpeg 使用 GPL build,需設定 VISIONA_ALLOW_GPL_FFMPEG=1' -# Makefile 需要 bash + make,透過 MSYS2 MinGW64 shell 執行 +# 讓 MSYS2 bash 繼承 Windows PATH(才找得到 go / pnpm / python / wails) +$env:MSYS2_PATH_TYPE = 'inherit' +$env:CHERE_INVOKING = '1' + +# Makefile 需要 bash + make,透過 MSYS2 bash 執行 # 將 Windows 路徑 C:\foo\bar 轉成 MSYS2 路徑 /c/foo/bar $projectPath = (Get-Location).Path $msysPath = '/' + $projectPath.Substring(0,1).ToLower() + '/' + `