From 019df7bc237c956ec69461e738a6c5828891578e Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 7 Jul 2026 17:58:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=BE=E6=A0=87=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ Makefile | 13 +++++++--- resources/genico/main.go | 51 ++++++++++++++++++++++++++++++++++++++++ resources/lmvpn.rc | 1 + 4 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 resources/genico/main.go create mode 100644 resources/lmvpn.rc diff --git a/.gitignore b/.gitignore index c8d3322..ce0a6a0 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ *.app *.dmg *.exe +*.syso +resources/icon.ico # Go /vendor/ diff --git a/Makefile b/Makefile index e1e5de3..ba50077 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,10 @@ APP_BUNDLE = $(APP_NAME).app GO = go CGO_ENABLED = 1 GIT_HASH = $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) -VERSION = 0.3.5-$(GIT_HASH) +VERSION = 0.3.6-$(GIT_HASH) LDFLAGS = -s -w -X lmvpn/internal/version.Version=$(VERSION) -.PHONY: all build app run daemon clean vet tidy fmt icon build-windows +.PHONY: all build app run daemon clean vet tidy fmt icon icon-windows build-windows ## all: build the .app bundle (default) all: app @@ -81,8 +81,15 @@ fmt: clean: rm -rf $(BUILD_DIR) $(APP_BUNDLE) +## icon-windows: generate icon.ico and compile Windows resource (.syso) +icon-windows: + go run resources/genico/main.go + x86_64-w64-mingw32-windres -i resources/lmvpn.rc -O coff -o cmd/lmvpn/resource_windows_amd64.syso + x86_64-w64-mingw32-windres -i resources/lmvpn.rc -O coff -o cmd/lmvpnd/resource_windows_amd64.syso + @echo "Generated Windows icon resources" + ## build-windows: cross-compile Windows x86_64 exes (requires mingw-w64) -build-windows: +build-windows: icon-windows mkdir -p $(BUILD_DIR) CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc \ $(GO) build -ldflags "$(LDFLAGS) -H windowsgui" -o $(BUILD_DIR)/$(GUI_BIN).exe ./cmd/lmvpn diff --git a/resources/genico/main.go b/resources/genico/main.go new file mode 100644 index 0000000..e941b9f --- /dev/null +++ b/resources/genico/main.go @@ -0,0 +1,51 @@ +// genico converts resources/icon.png into a Windows .ico file using the +// PNG-in-ICO format (the PNG bytes are wrapped in a minimal ICO container +// without decoding/re-encoding). Works on Windows Vista and later. +// +// Run: go run resources/genico/main.go +package main + +import ( + "encoding/binary" + "fmt" + "os" +) + +func main() { + pngData, err := os.ReadFile("resources/icon.png") + if err != nil { + fmt.Fprintf(os.Stderr, "genico: %v\n", err) + os.Exit(1) + } + + // ICO header (6 bytes) + one directory entry (16 bytes) = 22 bytes overhead. + const headerSize = 6 + const entrySize = 16 + dataOffset := uint32(headerSize + entrySize) + + ico := make([]byte, 0, headerSize+entrySize+len(pngData)) + + // ICONDIR + ico = binary.LittleEndian.AppendUint16(ico, 0) // reserved + ico = binary.LittleEndian.AppendUint16(ico, 1) // type = icon + ico = binary.LittleEndian.AppendUint16(ico, 1) // count = 1 image + + // ICONDIRENTRY + ico = append(ico, 0) // width (0 = 256+, actual size in PNG header) + ico = append(ico, 0) // height (0 = 256+, actual size in PNG header) + ico = append(ico, 0) // color count (0 = ≥256 colors) + ico = append(ico, 0) // reserved + ico = binary.LittleEndian.AppendUint16(ico, 1) // planes + ico = binary.LittleEndian.AppendUint16(ico, 32) // bit count + ico = binary.LittleEndian.AppendUint32(ico, uint32(len(pngData))) + ico = binary.LittleEndian.AppendUint32(ico, dataOffset) + + // PNG image data + ico = append(ico, pngData...) + + if err := os.WriteFile("resources/icon.ico", ico, 0644); err != nil { + fmt.Fprintf(os.Stderr, "genico: %v\n", err) + os.Exit(1) + } + fmt.Println("Generated resources/icon.ico") +} diff --git a/resources/lmvpn.rc b/resources/lmvpn.rc new file mode 100644 index 0000000..ce8761c --- /dev/null +++ b/resources/lmvpn.rc @@ -0,0 +1 @@ +LMVPN ICON "resources/icon.ico"