From 08001e42dedfdf64cbb3a1cb9c240959f98a3dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A2=A8=E9=9B=AA?= Date: Wed, 19 Aug 2026 20:59:55 +0800 Subject: [PATCH] feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 feat(release): pure-Go static multi-arch Linux builds (CGO=0 + modernc sqlite) Architectures: amd64(v1), arm64, armv7, armv6, 386, riscv64, loong64, ppc64le, s390x Portable on glibc and musl without system libsqlite3 --- .github/workflows/release.yml | 62 +++++++++++++++++++++++++++++++---- Makefile | 29 ++++++++++------ 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3662feb..1773ca2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,6 @@ name: Release · Ant Design +# Pure-Go static binaries (CGO_ENABLED=0 + modernc sqlite) for maximum Linux portability: +# works on glibc and musl (Alpine), old and new distros, without system libsqlite3. on: push: tags: @@ -18,13 +20,28 @@ jobs: fail-fast: false matrix: include: + # x86_64 — GOAMD64=v1 for broadest CPU compatibility (pre-AVX hosts) - goarch: amd64 + goamd64: v1 artifact: linux-amd64 - goarch: arm64 artifact: linux-arm64 - goarch: arm goarm: '7' artifact: linux-armv7 + - goarch: arm + goarm: '6' + artifact: linux-armv6 + - goarch: '386' + artifact: linux-386 + - goarch: riscv64 + artifact: linux-riscv64 + - goarch: loong64 + artifact: linux-loong64 + - goarch: ppc64le + artifact: linux-ppc64le + - goarch: s390x + artifact: linux-s390x runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -43,19 +60,34 @@ jobs: run: | rm -rf backend/cmd/server/web/dist cp -r frontend/dist backend/cmd/server/web/dist - - name: Build backend + - name: Build static backend (${{ matrix.artifact }}) working-directory: backend env: + CGO_ENABLED: '0' GOOS: linux GOARCH: ${{ matrix.goarch }} GOARM: ${{ matrix.goarm }} - run: go build -trimpath -ldflags='-s -w' -o "../3m-ui-${{ matrix.artifact }}" ./cmd/server + GOAMD64: ${{ matrix.goamd64 }} + run: | + go build -tags sqlite_modernc -trimpath -ldflags='-s -w' \ + -o "../3m-ui-${{ matrix.artifact }}" ./cmd/server + file "../3m-ui-${{ matrix.artifact }}" || true + if command -v ldd >/dev/null 2>&1; then + if ldd "../3m-ui-${{ matrix.artifact }}" 2>&1 | grep -qiE 'not a dynamic|statically linked'; then + echo "OK: static binary" + else + echo "WARN: binary may be dynamically linked:" + ldd "../3m-ui-${{ matrix.artifact }}" || true + fi + fi - name: Archive run: tar -czf "3m-ui-${{ matrix.artifact }}.tar.gz" "3m-ui-${{ matrix.artifact }}" - uses: actions/upload-artifact@v4 with: name: archive-${{ matrix.artifact }} - path: 3m-ui-${{ matrix.artifact }}.tar.gz + path: | + 3m-ui-${{ matrix.artifact }} + 3m-ui-${{ matrix.artifact }}.tar.gz release: needs: build @@ -65,6 +97,8 @@ jobs: with: path: artifacts merge-multiple: true + - name: List artifacts + run: find artifacts -type f | sort - name: Resolve tag id: meta run: | @@ -84,7 +118,23 @@ jobs: body: | ## Packages - Official frontend: Ant Design. + Official frontend: **Ant Design**. - Architectures: `amd64`, `arm64`, `armv7`. - files: artifacts/*.tar.gz + All binaries are **pure-Go static** (`CGO_ENABLED=0` + `modernc` SQLite): + run on glibc *and* musl (Alpine), without system `libsqlite3`. + + | Artifact | Architecture | + |---|---| + | `3m-ui-linux-amd64` | x86_64 (GOAMD64=v1) | + | `3m-ui-linux-arm64` | aarch64 | + | `3m-ui-linux-armv7` | ARMv7 | + | `3m-ui-linux-armv6` | ARMv6 (e.g. older Pi) | + | `3m-ui-linux-386` | i386 / i686 | + | `3m-ui-linux-riscv64` | RISC-V 64 | + | `3m-ui-linux-loong64` | LoongArch64 | + | `3m-ui-linux-ppc64le` | POWER little-endian | + | `3m-ui-linux-s390x` | IBM Z | + + Each arch is also published as `.tar.gz`. + files: | + artifacts/3m-ui-linux-* diff --git a/Makefile b/Makefile index aaba363..36a2377 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,10 @@ GIT_COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown) BUILD_TIME ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ) LDFLAGS := -s -w -X main.version=$(VERSION) -X main.gitCommit=$(GIT_COMMIT) -X main.buildTime=$(BUILD_TIME) +# Pure-Go static build flags (portable across glibc/musl Linux). +STATIC_TAGS := sqlite_modernc +STATIC_ENV := CGO_ENABLED=0 + .PHONY: build frontend-assets build-linux build-linux-static release clean # Build the web UI and copy the complete Vite output into the directory used @@ -18,24 +22,29 @@ frontend-assets: mkdir -p $(BACKEND_DIR)/cmd/server/web cp -R $(FRONTEND_DIR)/dist $(BACKEND_DIR)/cmd/server/web/dist +# Local / host build (uses default sqlite driver; may require CGO on some setups). build: frontend-assets mkdir -p $(DIST_DIR) cd $(BACKEND_DIR) && go build -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME) ./cmd/server +# All official Linux release targets: pure static, max portability. build-linux: frontend-assets mkdir -p $(DIST_DIR) - cd $(BACKEND_DIR) && GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-amd64 ./cmd/server - cd $(BACKEND_DIR) && GOOS=linux GOARCH=arm64 CGO_ENABLED=1 go build -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-arm64 ./cmd/server - cd $(BACKEND_DIR) && GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=1 go build -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-armv7 ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=amd64 GOAMD64=v1 go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-amd64 ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=arm64 go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-arm64 ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=arm GOARM=7 go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-armv7 ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=arm GOARM=6 go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-armv6 ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=386 go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-386 ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=riscv64 go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-riscv64 ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=loong64 go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-loong64 ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=ppc64le go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-ppc64le ./cmd/server + cd $(BACKEND_DIR) && $(STATIC_ENV) GOOS=linux GOARCH=s390x go build -tags $(STATIC_TAGS) -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-s390x ./cmd/server -build-linux-static: frontend-assets - mkdir -p $(DIST_DIR) - cd $(BACKEND_DIR) && GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -tags sqlite_modernc -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-amd64-static ./cmd/server - cd $(BACKEND_DIR) && GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -tags sqlite_modernc -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-arm64-static ./cmd/server - cd $(BACKEND_DIR) && GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=0 go build -tags sqlite_modernc -trimpath -ldflags "$(LDFLAGS)" -o ../$(DIST_DIR)/$(APP_NAME)-linux-armv7-static ./cmd/server +# Alias: static is the only official release mode. +build-linux-static: build-linux -release: clean build build-linux build-linux-static - cp scripts/install.sh scripts/update.sh scripts/uninstall.sh $(DIST_DIR)/ +release: clean build-linux + cp scripts/install.sh scripts/update.sh scripts/uninstall.sh scripts/3m-ui.sh scripts/3m-ui $(DIST_DIR)/ clean: rm -rf $(DIST_DIR)