diff --git a/.woodpecker.yaml b/.woodpecker.yaml
index 44fbbe0..ccd1d29 100644
--- a/.woodpecker.yaml
+++ b/.woodpecker.yaml
@@ -10,6 +10,11 @@ steps:
commands:
- make ci-export
+ - name: binaries
+ image: git.teletypegames.org/internal/love-builder:latest
+ commands:
+ - make ci-binaries
+
- name: upload
image: alpine
environment:
diff --git a/Makefile b/Makefile
index edd174a..f90b1da 100644
--- a/Makefile
+++ b/Makefile
@@ -59,6 +59,97 @@ web: love
sed -i.bak 's|||g' $(WEB_DIR)/index.html && rm $(WEB_DIR)/index.html.bak
@echo "==> Web build ready in $(WEB_DIR)"
+# -----------------------------------------
+# Native (fused) binaries from the official LÖVE releases.
+# The love-builder CI image pre-fetches the dist files to /opt/love-dist;
+# local builds fall back to downloading them from GitHub.
+# win: love.exe + .love concatenated; mac: .love dropped into the
+# official (universal) love.app; linux: the official AppImage taken
+# apart, the .love fused into bin/love, then reassembled with
+# mksquashfs (squashfs-tools required).
+# -----------------------------------------
+
+LOVE_VERSION = 11.5
+LOVE_BASE_URL = https://github.com/love2d/love/releases/download/$(LOVE_VERSION)
+LOVE_CACHE_DIR = /opt/love-dist
+
+BINARY_SLUGS = win-x64 mac-universal linux-x64
+
+# $(1) dist file name
+define f_fetch_love
+ mkdir -p $(DIST_DIR); \
+ if [ -f "$(LOVE_CACHE_DIR)/$(1)" ]; then \
+ echo "==> Using cached $(1)"; \
+ cp "$(LOVE_CACHE_DIR)/$(1)" "$(DIST_DIR)/$(1)"; \
+ elif [ ! -f "$(DIST_DIR)/$(1)" ]; then \
+ echo "==> Downloading $(1)"; \
+ curl -sSL "$(LOVE_BASE_URL)/$(1)" -o "$(DIST_DIR)/$(1)"; \
+ fi
+endef
+
+binaries:
+ @if [ -z "$(VERSION)" ]; then \
+ echo "ERROR: VERSION not set!"; exit 1; \
+ fi
+ @$(MAKE) binary-win binary-mac binary-linux VERSION=$(VERSION)
+
+binary-win: love
+ @echo "==> Fusing windows binary"
+ @$(call f_fetch_love,love-$(LOVE_VERSION)-win64.zip)
+ @set -e; \
+ PKG_DIR="$(PROJECT)-$(VERSION)-win-x64"; \
+ rm -rf "$$PKG_DIR" "$$PKG_DIR.zip" $(DIST_DIR)/win64; \
+ unzip -q $(DIST_DIR)/love-$(LOVE_VERSION)-win64.zip -d $(DIST_DIR)/win64; \
+ SRC=$$(dirname $$(find $(DIST_DIR)/win64 -name love.exe | head -n 1)); \
+ mkdir -p "$$PKG_DIR"; \
+ cat "$$SRC/love.exe" $(OUTPUT_LOVE) > "$$PKG_DIR/$(PROJECT).exe"; \
+ cp "$$SRC"/*.dll "$$PKG_DIR/"; \
+ cp "$$SRC/license.txt" "$$PKG_DIR/" 2>/dev/null || true; \
+ zip -qr "$$PKG_DIR.zip" "$$PKG_DIR"; \
+ rm -rf "$$PKG_DIR" $(DIST_DIR)/win64; \
+ echo "==> $$PKG_DIR.zip kesz"
+
+binary-mac: love
+ @echo "==> Fusing macOS app bundle"
+ @$(call f_fetch_love,love-$(LOVE_VERSION)-macos.zip)
+ @set -e; \
+ PKG_DIR="$(PROJECT)-$(VERSION)-mac-universal"; \
+ rm -rf "$$PKG_DIR" "$$PKG_DIR.zip" $(DIST_DIR)/macos; \
+ unzip -q $(DIST_DIR)/love-$(LOVE_VERSION)-macos.zip -d $(DIST_DIR)/macos; \
+ mkdir -p "$$PKG_DIR"; \
+ mv $(DIST_DIR)/macos/love.app "$$PKG_DIR/$(PROJECT).app"; \
+ cp $(OUTPUT_LOVE) "$$PKG_DIR/$(PROJECT).app/Contents/Resources/"; \
+ PLIST="$$PKG_DIR/$(PROJECT).app/Contents/Info.plist"; \
+ sed -i.bak "s|LÖVE|$(PROJECT)|g" "$$PLIST" && rm "$$PLIST.bak"; \
+ sed -i.bak "s|org\.love2d\.love|org.teletypegames.$(PROJECT)|g" "$$PLIST" && rm "$$PLIST.bak"; \
+ zip -qry "$$PKG_DIR.zip" "$$PKG_DIR"; \
+ rm -rf "$$PKG_DIR" $(DIST_DIR)/macos; \
+ echo "==> $$PKG_DIR.zip kesz"
+
+# Az AppImage runtime glibc-dinamikus, alpine (musl) alatt nem futtatható,
+# ezért nem a runtime-ot futtatjuk: az offsetet readelf-ből számoljuk
+# (shoff + shentsize*shnum), a squashfs-t unsquashfs -o bontja ki.
+binary-linux: love
+ @echo "==> Fusing linux AppImage"
+ @$(call f_fetch_love,love-$(LOVE_VERSION)-x86_64.AppImage)
+ @set -e; \
+ PKG_DIR="$(PROJECT)-$(VERSION)-linux-x64"; \
+ APPIMAGE="$(DIST_DIR)/love-$(LOVE_VERSION)-x86_64.AppImage"; \
+ rm -rf "$$PKG_DIR" "$$PKG_DIR.zip" squashfs-root $(DIST_DIR)/game.squashfs $(DIST_DIR)/runtime; \
+ OFFSET=$$(readelf -h "$$APPIMAGE" | awk '/Start of section headers/{o=$$5} /Size of section headers/{s=$$5} /Number of section headers/{n=$$5} END{print o+s*n}'); \
+ unsquashfs -q -o $$OFFSET -d squashfs-root "$$APPIMAGE" >/dev/null; \
+ cat squashfs-root/bin/love $(OUTPUT_LOVE) > squashfs-root/bin/love.fused; \
+ mv squashfs-root/bin/love.fused squashfs-root/bin/love; \
+ chmod +x squashfs-root/bin/love; \
+ mksquashfs squashfs-root $(DIST_DIR)/game.squashfs -root-owned -noappend -quiet -comp gzip; \
+ head -c $$OFFSET "$$APPIMAGE" > $(DIST_DIR)/runtime; \
+ mkdir -p "$$PKG_DIR"; \
+ cat $(DIST_DIR)/runtime $(DIST_DIR)/game.squashfs > "$$PKG_DIR/$(PROJECT).AppImage"; \
+ chmod +x "$$PKG_DIR/$(PROJECT).AppImage"; \
+ zip -qr "$$PKG_DIR.zip" "$$PKG_DIR"; \
+ rm -rf "$$PKG_DIR" squashfs-root $(DIST_DIR)/game.squashfs $(DIST_DIR)/runtime; \
+ echo "==> $$PKG_DIR.zip kesz"
+
export: love web
@if [ -z "$(VERSION)" ]; then \
echo "ERROR: VERSION not set!"; exit 1; \
@@ -93,6 +184,10 @@ ci-export:
@VERSION=$$(cat $(VERSION_FILE)); \
$(MAKE) export VERSION=$$VERSION
+ci-binaries:
+ @VERSION=$$(cat $(VERSION_FILE)); \
+ $(MAKE) binaries VERSION=$$VERSION
+
ci-upload:
@VERSION=$$(cat $(VERSION_FILE)); \
FILE_LOVE="$(PROJECT)-$$VERSION.love.zip"; \
@@ -100,8 +195,12 @@ ci-upload:
META_SRC="metadata.json"; \
META_DST="$(PROJECT)-$$VERSION.metadata.json"; \
cp $$META_SRC $$META_DST; \
+ BINS=""; \
+ for slug in $(BINARY_SLUGS); do \
+ [ -f "$(PROJECT)-$$VERSION-$$slug.zip" ] && BINS="$$BINS $(PROJECT)-$$VERSION-$$slug.zip"; \
+ done; \
sshpass -p "$(DROPAREA_SSH_PASSWORD)" scp -o StrictHostKeyChecking=no -P $(DROPAREA_PORT) \
- $$FILE_LOVE $$FILE_WEB $$META_DST \
+ $$FILE_LOVE $$FILE_WEB $$META_DST $$BINS \
$(DROPAREA_USER)@$(DROPAREA_HOST):$(DROPAREA_TARGET_PATH)/
ci-update:
@@ -109,4 +208,4 @@ ci-update:
curl "$(UPDATE_SERVER)/update?secret=$(UPDATE_SECRET)&name=$(PROJECT)&platform=love&version=$$VERSION"; \
curl "$(UPDATE_SERVER)/update?secret=$(UPDATE_SECRET)&name=$(PROJECT)&platform=love-web&version=$$VERSION"
-.PHONY: all build love web export watch clean ci-version ci-export ci-upload ci-update
\ No newline at end of file
+.PHONY: all build love web export binaries binary-win binary-mac binary-linux watch clean ci-version ci-export ci-binaries ci-upload ci-update
\ No newline at end of file