feat(t77-lite): Windows 合併成單一 exe——go:embed 把 collector 吃進 tray

leo 07-28:「Windows 解開有 2 個 exe,被瀏覽器擋住,如果只有 1 個,
我還可以把 exe 改成 e_e 讓朋友改回來,但現在這樣完全不行」。
做法:build-windows.sh 先編 collector.exe 到 tray 目錄供 //go:embed,
tray 啟動時 ensureEmbeddedCollector() sha256 比對後解壓到 ~/.arcrun-rag/bin/,
失敗 fallback 同層(舊版相容);Mac 走 build-tag no-op 完全不動。
驗收(總管親跑):PE32+ GUI exe/zip 僅 1 檔 16.9MB<20MB jsDelivr 上限/
collector 特徵字串在 exe 肚裡(grep=1)/Mac go build+test 全綠/tray 測試綠。
(實作=子 CC;build+驗收+commit=總管)
This commit is contained in:
2026-07-28 12:15:13 +08:00
parent 0deef3dbd9
commit 5e122b47ec
4 changed files with 63 additions and 12 deletions
+18 -11
View File
@@ -5,12 +5,16 @@
# 不需要 Docker、不需要 fyne-cross。條件只有一個——裝 mingw-w64。
# (這推翻了先前「fyne GUI 編不了 CGo+GL → 歸屬真機」的假設;2026-07-27 本機實測通過。)
#
# t77-lite2026-07-28):arcrun-collector.exe 用 //go:embed 吃進 tray
# 產物只剩一個 exe,瀏覽器不再多擋一個(leo:「如果只有 1 個,我還可以把 exe 改成 e_e
# 讓朋友改回來,但現在這樣完全不行」)。
#
# 前置(一次就好):
# brew install mingw-w64 # 提供 x86_64-w64-mingw32-gcc
#
# 用法:
# cd collector/cmd/arcrun-tray && bash build-windows.sh
# 產物:dist-windows/ArcrunRAG-win-unsigned.zip(含 arcrun-tray.exe arcrun-collector.exe
# 產物:dist-windows/ArcrunRAG-win-unsigned.zip含 arcrun-tray.exe
#
# ⚠️ 誠實界定:**本腳本只證明「編得出來」,沒證明「跑起來對」**。
# 托盤 icon 會不會出現、選資料夾對話框、SmartScreen 實際攔截行為,
@@ -37,27 +41,30 @@ echo " $($CC_WIN --version | head -1)"
rm -rf "$OUT" && mkdir -p "$OUT"
echo "② 編 collector.exe(純 stdlibCGO_ENABLED=0 即可"
echo "② 編 collector.exe 到本目錄(供 //go:embed 吃進 tray"
( cd ../.. && CGO_ENABLED=0 GOOS=windows GOARCH=amd64 \
go build -ldflags "-s -w" -o "cmd/arcrun-tray/$OUT/arcrun-collector.exe" . )
go build -ldflags "-s -w" -o "cmd/arcrun-tray/arcrun-collector.exe" . )
echo "③ 編托盤 GUIfyneCGo+GL,走 mingw-H windowsgui=不彈黑色命令列視窗"
echo "③ 編托盤 GUIfyneCGo+GL,走 mingwcollector.exe embed 進去成為單一 exe"
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC="$CC_WIN" \
go build -ldflags "-H windowsgui -s -w ${LDFLAGS_VER}" -o "$OUT/arcrun-tray.exe" .
echo "④ 打包 zip"
( cd "$OUT" && zip -9 -q ArcrunRAG-win-unsigned.zip arcrun-tray.exe arcrun-collector.exe )
echo "④ 打包 zip(單一 exe,瀏覽器下載只有一個)"
( cd "$OUT" && zip -9 -q ArcrunRAG-win-unsigned.zip arcrun-tray.exe )
echo "⑤ 刪除本目錄臨時用的 collector.exe(已 embed 進 tray,不進版控)"
rm -f arcrun-collector.exe
echo
echo "✅ 完成:$OUT/ArcrunRAG-win-unsigned.zip"
ls -lh "$OUT"/*.exe "$OUT"/*.zip | awk '{print " "$9" "$5}'
echo
echo "📏 2026-07-27 本機實測基準(差太多就是哪裡不對):"
echo " arcrun-tray.exe ~23.5 MB未加 -s -w 是 ~40.8 MB"
echo " arcrun-collector.exe ~6.5 MB"
echo " zip 合計 ~13.9 MB ← **在 jsDelivr 20MB 上限內**Mac 版 21MB 超標故走 GitHub raw"
echo "📏 體積基準(t77-lite embed 後 tray 吃進 collector+~6.5 MB):"
echo " arcrun-tray.exe ~30 MB(含內嵌 collector未加 -s -w 是 ~47 MB"
echo " zip 單檔 ~14 MB(和舊版雙檔 zip 相近,同樣在 jsDelivr 20 MB 上限內)"
echo
echo "🔬 驗法(這台機器上驗得到的部分):"
echo " file $OUT/arcrun-tray.exe → 應為 'PE32+ executable (GUI) x86-64, for MS Windows'"
echo " file $OUT/arcrun-collector.exe → 應為 'PE32+ executable (console) x86-64'"
echo " unzip -l $OUT/ArcrunRAG-win-unsigned.zip → 只應有 arcrun-tray.exe 一個檔案"
echo " grep -c 'PDF 打不開' $OUT/arcrun-tray.exe → 應輸出 1collector 特徵字串在肚裡)"
echo "⛔ 驗不到、必須真 Windows 機器的部分:托盤 icon 顯示/選資料夾對話框/SmartScreen 實際行為。"
+5
View File
@@ -0,0 +1,5 @@
//go:build !windows
package main
func ensureEmbeddedCollector() (string, error) { return "", nil }
+34
View File
@@ -0,0 +1,34 @@
//go:build windows
package main
import (
"crypto/sha256"
_ "embed"
"os"
"path/filepath"
)
//go:embed arcrun-collector.exe
var collectorExeBytes []byte
// ensureEmbeddedCollector 把內嵌的 collector.exe 解壓到 ~/.arcrun-rag/bin/。
// 用 sha256 比對避免每次啟動都重寫磁碟;回傳可執行的絕對路徑。
// t77-liteleo 2026-07-28:「Windows 解開有 2 個 exe 被瀏覽器擋住;如果只有 1 個,
// 我還可以把 exe 改成 e_e 讓朋友改回來」)
func ensureEmbeddedCollector() (string, error) {
dest := filepath.Join(appDir(), "bin", "arcrun-collector.exe")
embedded := sha256.Sum256(collectorExeBytes)
if existing, err := os.ReadFile(dest); err == nil {
if sha256.Sum256(existing) == embedded {
return dest, nil
}
}
if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil {
return "", err
}
if err := os.WriteFile(dest, collectorExeBytes, 0o755); err != nil {
return "", err
}
return dest, nil
}
+6 -1
View File
@@ -176,8 +176,13 @@ func saveConfig(c *directConfig) error {
return os.WriteFile(configPath(), data, 0o600)
}
// collectorBinPath 找同綑的 collector 執行檔app bundle 內與托盤同層)
// collectorBinPath 找可用的 collector 執行檔。
// Windows 上先嘗試從內嵌位元組解壓到 ~/.arcrun-rag/bin/embed_windows.got77-lite),
// 解壓失敗才 fallback 同層目錄;Mac 直接走同層路徑,完全不受影響。
func collectorBinPath() string {
if p, err := ensureEmbeddedCollector(); err == nil && p != "" {
return p
}
exe, err := os.Executable()
if err != nil {
return "arcrun-collector"