feat(builder): declare multi-arch builds with ARCHES

Project architecture lists belong in makefile.builder, not .env.builder.
deb/push-deb fan out when ARCH is omitted; Docker platforms derive from
ARCHES. Legacy makefiles without ARCHES keep the old single-arch behavior.
This commit is contained in:
2026-09-08 16:31:53 +08:00
parent c248c3f0e3
commit aa7a265e76
9 changed files with 433 additions and 36 deletions
+1 -1
View File
@@ -10,4 +10,4 @@
# DOCKER_REGISTRY=
# DOCKER_REPOSITORY=
# IMAGE_TAG=
# PLATFORMS=
# PLATFORMS= # optional override; project ARCHES lives in makefile.builder
+43 -8
View File
@@ -2,13 +2,26 @@
# 不要把这些目标写进用户的 Makefile / makefile。
# 初始化时按项目轨道删掉未使用的 deb / docker 段。
# 把 build 的 TODO 换成真实编译命令;禁止在 build / deb / docker 里上传。
# build 必须尊重 $(ARCH)。要发双架构时把 arm64 写进 ARCHES,不要改 .env.builder。
#
# include 路径见 references/contract.md。测试或非标准安装可设 BUILDER_SKILL_DIR。
ARCH ?= amd64
ifneq ($(filter $(ARCH),amd64 arm64),$(ARCH))
$(error ARCH must be amd64 or arm64)
ARCHES ?= amd64
ARCH ?= $(firstword $(ARCHES))
ifeq ($(strip $(ARCHES)),)
$(error ARCHES must not be empty)
endif
ifneq ($(filter-out amd64 arm64,$(ARCHES)),)
$(error ARCHES entries must be amd64 or arm64)
endif
ifneq ($(filter $(ARCH),$(ARCHES)),$(ARCH))
$(error ARCH must be one of: $(ARCHES))
endif
# Fan-out over ARCHES only when ARCH was not set on the CLI/environment.
_ARCH_FROM_FILE := $(filter file default undefined,$(origin ARCH))
_MULTI_ARCH := $(and $(_ARCH_FROM_FILE),$(filter-out 1,$(words $(ARCHES))))
_PUSH_DEB_ARCHES := $(if $(_ARCH_FROM_FILE),$(ARCHES),$(ARCH))
PROJECT_NAME ?= $(notdir $(CURDIR))
DIST_DIR ?= dist
@@ -21,40 +34,62 @@ endif
BUILDER_SCRIPTS := $(or $(BUILDER_SKILL_DIR),$(HOME)/.pouch/skills/builder)/scripts
.PHONY: help version clean build deb docker push push-deb push-docker
.PHONY: help version arches clean build deb docker push push-deb push-docker
help:
@echo "$(PROJECT_NAME) $(VERSION)"
@echo " ARCHES=$(ARCHES) ARCH=$(ARCH)"
@echo " make -f makefile.builder build [ARCH=amd64|arm64] - 构建主产物 / build"
@echo " make -f makefile.builder version - 打印规范版本 / canonical version"
@echo " make -f makefile.builder arches - 打印架构清单 / print ARCHES"
@echo " make -f makefile.builder clean - 删除 $(DIST_DIR)"
@echo " make -f makefile.builder deb - 打 DEB(只构建不上传)"
@echo " make -f makefile.builder deb - 打 DEB(按 ARCHES;只构建不上传)"
@echo " make -f makefile.builder docker - 本地单平台镜像"
@echo " make -f makefile.builder push / push-deb / push-docker"
version:
@echo $(VERSION)
arches:
@echo $(ARCHES)
clean:
rm -rf $(DIST_DIR)
# 替换为项目真实构建命令。不得 curl/scp/docker push。
# 替换为项目真实构建命令,且必须使用 $(ARCH)。不得 curl/scp/docker push。
build:
mkdir -p $(DIST_DIR)
@echo "TODO: build $(PROJECT_NAME) for linux/$(ARCH)"
ifdef _MULTI_ARCH
deb:
$(foreach a,$(ARCHES),$(MAKE) -f makefile.builder --no-print-directory deb ARCH=$(a) &&) true
else
deb: build
mkdir -p $(DIST_DIR)
dpkg-deb --build packaging $(DIST_DIR)/$(PROJECT_NAME)_$(VERSION)_$(ARCH).deb
rm -rf $(DIST_DIR)/packaging-$(ARCH)
cp -a packaging $(DIST_DIR)/packaging-$(ARCH)
sed -e 's/^Architecture:.*/Architecture: $(ARCH)/' \
$(DIST_DIR)/packaging-$(ARCH)/DEBIAN/control \
> $(DIST_DIR)/packaging-$(ARCH)/DEBIAN/control.stamped
mv $(DIST_DIR)/packaging-$(ARCH)/DEBIAN/control.stamped \
$(DIST_DIR)/packaging-$(ARCH)/DEBIAN/control
dpkg-deb --build $(DIST_DIR)/packaging-$(ARCH) $(DIST_DIR)/$(PROJECT_NAME)_$(VERSION)_$(ARCH).deb
endif
docker:
docker build --platform=linux/$(ARCH) -t $(PROJECT_NAME):$(IMAGE_TAG) .
push-deb:
$(BUILDER_SCRIPTS)/upload_deb.sh $(DIST_DIR)/$(PROJECT_NAME)_$(VERSION)_$(ARCH).deb
$(BUILDER_SCRIPTS)/upload_deb.sh $(foreach a,$(_PUSH_DEB_ARCHES),$(DIST_DIR)/$(PROJECT_NAME)_$(VERSION)_$(a).deb)
ifdef _ARCH_FROM_FILE
push-docker:
$(BUILDER_SCRIPTS)/publish_docker.sh
else
push-docker:
PLATFORMS=linux/$(ARCH) $(BUILDER_SCRIPTS)/publish_docker.sh
endif
# 单产物项目只保留一条 push。双产物改为:push: push-deb push-docker
push: push-deb