Added optimized device builds and harden the Embedded toolchain setup in both the PlayDate bindings and HelloPlayDate example targets.
This commit is contained in:
@@ -18,6 +18,21 @@ The script compiles the game as a dylib, places it in `Source/` next to
|
|||||||
|
|
||||||
## Device builds
|
## Device builds
|
||||||
|
|
||||||
Running on hardware requires the Embedded Swift + ARM toolchain pipeline
|
The Makefile cross-compiles the game with Embedded Swift and packages a
|
||||||
(see the repository README and Apple's swift-playdate-examples for the
|
`HelloPlaydate.pdx` containing both the device binary and the simulator
|
||||||
Makefile setup). This example covers the simulator workflow only.
|
dylib. It needs:
|
||||||
|
|
||||||
|
- the Playdate SDK (`PLAYDATE_SDK_PATH`, or the path in `~/.Playdate/config`),
|
||||||
|
- the Arm GNU toolchain (`arm-none-eabi-gcc`) on `PATH`,
|
||||||
|
- a swift.org development-snapshot toolchain (Xcode's toolchain does not
|
||||||
|
ship the Embedded Swift stdlib for the device target). A toolchain
|
||||||
|
installed at `~/Library/Developer/Toolchains` is picked up automatically;
|
||||||
|
otherwise pass `TOOLCHAINS=<bundle id>`.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
Swift code is compiled with `-Osize` by default; use `make SWIFT_OPT=-O` to
|
||||||
|
favor speed over size. Sideload the pdx from the Playdate Simulator
|
||||||
|
(Device > Upload Game to Device) or with the SDK's `pdutil`.
|
||||||
|
|||||||
Binary file not shown.
+21
-2
@@ -4,7 +4,7 @@ STACK_SIZE = 61800
|
|||||||
# Locate the Playdate SDK
|
# Locate the Playdate SDK
|
||||||
SDK = ${PLAYDATE_SDK_PATH}
|
SDK = ${PLAYDATE_SDK_PATH}
|
||||||
ifeq ($(SDK),)
|
ifeq ($(SDK),)
|
||||||
SDK = $(shell egrep '^\s*SDKRoot' ~/.Playdate/config | head -n 1 | cut -c9-)
|
SDK = $(shell sed -nE 's/^[[:space:]]*SDKRoot[[:space:]]+//p' ~/.Playdate/config | head -n 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SDK),)
|
ifeq ($(SDK),)
|
||||||
@@ -28,18 +28,37 @@ else
|
|||||||
$(error Swift toolchain not found; set ENV value TOOLCHAINS (e.g. TOOLCHAINS=org.swift.59202403121a make))
|
$(error Swift toolchain not found; set ENV value TOOLCHAINS (e.g. TOOLCHAINS=org.swift.59202403121a make))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Note: paths containing spaces are not supported (make word-splits them).
|
||||||
GCC_INCLUDE_PATHS := $(shell $(CC) -E -Wp,-v -xc /dev/null 2>&1 | egrep '^ ' | xargs echo )
|
GCC_INCLUDE_PATHS := $(shell $(CC) -E -Wp,-v -xc /dev/null 2>&1 | egrep '^ ' | xargs echo )
|
||||||
|
ifeq ($(GCC_INCLUDE_PATHS),)
|
||||||
|
$(error arm-none-eabi C headers not found; install the Arm GNU toolchain and ensure $(CC) is runnable)
|
||||||
|
endif
|
||||||
|
|
||||||
SWIFT_EXEC := "$(shell TOOLCHAINS=$(TOOLCHAINS) xcrun -f swiftc)"
|
SWIFT_EXEC := "$(shell TOOLCHAINS=$(TOOLCHAINS) xcrun -f swiftc)"
|
||||||
|
# With an unknown TOOLCHAINS id, xcrun silently falls back to Xcode's swiftc,
|
||||||
|
# which lacks the Embedded ARM stdlib; fail early with a clear message.
|
||||||
|
ifeq ($(findstring .xctoolchain,$(SWIFT_EXEC)),)
|
||||||
|
$(error swiftc for toolchain "$(TOOLCHAINS)" not found (xcrun returned $(SWIFT_EXEC)); install a swift.org toolchain or set TOOLCHAINS)
|
||||||
|
endif
|
||||||
TOOLCHAIN_PATH := $(shell echo $(SWIFT_EXEC)|sed s'/.xctoolchain.*/.xctoolchain/')
|
TOOLCHAIN_PATH := $(shell echo $(SWIFT_EXEC)|sed s'/.xctoolchain.*/.xctoolchain/')
|
||||||
|
|
||||||
$(info Using Swift toolchain "$(TOOLCHAINS)" (from $(TOOLCHAIN_PATH)))
|
$(info Using Swift toolchain "$(TOOLCHAINS)" (from $(TOOLCHAIN_PATH)))
|
||||||
|
|
||||||
|
# Optimization mode for Swift compiles. -Osize targets small code, which
|
||||||
|
# suits the device's flash/RAM budget (measured 15% smaller than -O on the
|
||||||
|
# HelloPlaydate example); override per-build for maximum speed instead:
|
||||||
|
# `make SWIFT_OPT=-O`. For larger games, appending
|
||||||
|
# `-Xfrontend -mergeable-symbols -Xfrontend -mergeable-traps` lets the
|
||||||
|
# linker deduplicate stdlib code specialized into both the wrapper and the
|
||||||
|
# game module.
|
||||||
|
SWIFT_OPT ?= -Osize
|
||||||
|
|
||||||
C_FLAGS := \
|
C_FLAGS := \
|
||||||
$(addprefix -I ,$(GCC_INCLUDE_PATHS)) \
|
$(addprefix -I ,$(GCC_INCLUDE_PATHS)) \
|
||||||
|
|
||||||
SWIFT_FLAGS := \
|
SWIFT_FLAGS := \
|
||||||
$(addprefix -Xcc , $(C_FLAGS)) \
|
$(addprefix -Xcc , $(C_FLAGS)) \
|
||||||
-O \
|
$(SWIFT_OPT) \
|
||||||
-wmo -enable-experimental-feature Embedded \
|
-wmo -enable-experimental-feature Embedded \
|
||||||
-Xfrontend -disable-stack-protector \
|
-Xfrontend -disable-stack-protector \
|
||||||
-Xfrontend -function-sections \
|
-Xfrontend -function-sections \
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ exec "$swift_bin" build \
|
|||||||
--triple armv7em-none-none-eabi \
|
--triple armv7em-none-none-eabi \
|
||||||
-Xswiftc -enable-experimental-feature -Xswiftc Embedded \
|
-Xswiftc -enable-experimental-feature -Xswiftc Embedded \
|
||||||
-Xswiftc -wmo \
|
-Xswiftc -wmo \
|
||||||
|
-Xswiftc -Osize \
|
||||||
-Xcc -I"$include_dir" \
|
-Xcc -I"$include_dir" \
|
||||||
-Xcc -mcpu=cortex-m7 \
|
-Xcc -mcpu=cortex-m7 \
|
||||||
-Xcc -mfloat-abi=hard \
|
-Xcc -mfloat-abi=hard \
|
||||||
|
|||||||
@@ -60,7 +60,10 @@ extension Graphics {
|
|||||||
/// Renders frame `frame` into the current context.
|
/// Renders frame `frame` into the current context.
|
||||||
public func renderFrame(_ frame: Int) throws(PlaydateError) {
|
public func renderFrame(_ frame: Int) throws(PlaydateError) {
|
||||||
guard videoAPI.pointee.renderFrame.unsafelyUnwrapped(pointer, Int32(frame)) != 0 else {
|
guard videoAPI.pointee.renderFrame.unsafelyUnwrapped(pointer, Int32(frame)) != 0 else {
|
||||||
throw PlaydateError(message: error ?? "unable to render frame \(frame)")
|
// Static message: the caller knows the frame it passed, and
|
||||||
|
// interpolating it would pull integer formatting machinery
|
||||||
|
// into the device binary.
|
||||||
|
throw PlaydateError(message: error ?? "unable to render frame")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -170,8 +170,10 @@ extension JSON {
|
|||||||
return try decode(file: file)
|
return try decode(file: file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Static message: interpolating the line number would pull integer
|
||||||
|
// formatting machinery into every device binary that decodes JSON.
|
||||||
private static func decodeError(_ context: DecodeContext) -> PlaydateError {
|
private static func decodeError(_ context: DecodeContext) -> PlaydateError {
|
||||||
PlaydateError(message: "\(context.errorMessage ?? "JSON decode failed") (line \(context.errorLine))")
|
PlaydateError(message: context.errorMessage ?? "JSON decode failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Encoding
|
// MARK: - Encoding
|
||||||
|
|||||||
Reference in New Issue
Block a user