carlos / todomvc-bakeoff Public

Clone
git clone https://amadan.net/carlos/todomvc-bakeoff

Plain git — no account needed to clone.

Download

Download this file

1# todo-spinel. See README.md for what each piece is.
2#
3# make build dist/app for this machine (x86-64, dynamic glibc)
4# make build-arm64 dist/app-linux-arm64 (static, aarch64)
5# make test test/run.sh against dist/app, plain and under GC stress
6# make deploy ship dist/app-linux-arm64 to Carloku
7
8SHELL := bash
9.SHELLFLAGS := -euo pipefail -c
10.DELETE_ON_ERROR:
11
12TC ?= $(HOME)/.local/share/bakeoff-toolchains
13SPINEL_HOST ?= $(TC)/spinel-src/spinel/bin/spinel
14SPINEL_ARM64?= $(TC)/spinel-arm64/bin/spinel
15TEP_SRC ?= $(TC)/spinel-src/tep
16SPINELKIT ?= $(TC)/spinel-src/spinelkit
17RUBY ?= $(shell PATH="$(HOME)/.pixi/bin:$$PATH" command -v ruby)
18ARM64 := $(abspath ../../scripts/arm64.sh)
19
20SQLITE_VER := 3500400
21SQLITE_ZIP := .cache/src/sqlite-amalgamation-$(SQLITE_VER).zip
22SQLITE_URL := https://www.sqlite.org/2025/sqlite-amalgamation-$(SQLITE_VER).zip
23SQLITE_SHA := 1d3049dd0f830a025a53105fc79fd2ab9431aea99e137809d064d8ee8356b032
24SQLITE_DIR := .cache/src/sqlite-amalgamation-$(SQLITE_VER)
25# One connection, used from one thread; no extension loading (static glibc
26# can't dlopen anyway).
27SQLITE_DEFS := -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_DQS=0 \
28 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS
29
30PATCHES := $(sort $(wildcard patches/*.patch))
31SOURCES := app.rb $(wildcard assets/static/*)
32VERSION := $(shell git rev-parse --short HEAD 2>/dev/null || echo dev)
33
34export LANG := C.UTF-8
35export LC_ALL := C.UTF-8
36export SPINELKIT_DIR := $(SPINELKIT)
37export TEP_QUIET := 1
38
39.PHONY: build build-arm64 test clean clean-deps bump unbump deploy deps FORCE
40
41build: dist/app
42build-arm64: dist/app-linux-arm64
43
44# ---- version stamp ---------------------------------------------------------
45# Rewritten only when the commit changes, so it doesn't force rebuilds.
46version.rb: FORCE
47 @printf '# Written by make; not checked in.\nAPP_VERSION = "%s"\n' '$(VERSION)' > $@.tmp
48 @if cmp -s $@.tmp $@; then rm $@.tmp; else mv $@.tmp $@; fi
49
50# ---- third-party sources (kept by clean-deps) -------------------------------
51$(SQLITE_ZIP):
52 mkdir -p $(@D)
53 curl -sSfL -o $@.part $(SQLITE_URL)
54 echo "$(SQLITE_SHA) $@.part" | sha256sum -c --quiet
55 mv $@.part $@
56
57$(SQLITE_DIR)/sqlite3.c: $(SQLITE_ZIP)
58 python3 -I -m zipfile -e $< .cache/src
59 touch $@
60
61# ---- per-target compiled deps (removed by clean-deps) -----------------------
62# A patched copy of tep per target: tep bakes the paths of its C shims
63# (sphttp.o, tep_sqlite.o) into the translated source, so each target's
64# copy holds that target's objects.
65.cache/%/tep/.patched: $(PATCHES)
66 rm -rf .cache/$*/tep
67 mkdir -p .cache/$*
68 cp -a $(TEP_SRC) .cache/$*/tep
69 rm -rf .cache/$*/tep/.git
70 for p in $(PATCHES); do patch -s -p1 -d .cache/$*/tep < $$p; done
71 touch $@
72
73# Host (x86-64): the system cc.
74.cache/x86/libsqlite3.a: $(SQLITE_DIR)/sqlite3.c
75 mkdir -p $(@D)
76 cc -O2 $(SQLITE_DEFS) -c $< -o .cache/x86/sqlite3.o
77 ar rcs $@ .cache/x86/sqlite3.o
78
79.cache/x86/tep/tep/sphttp.o: .cache/x86/tep/.patched
80 cc -O2 -c .cache/x86/tep/tep/sphttp.c -o $@
81
82.cache/x86/tep/native/sqlite/tep_sqlite.o: .cache/x86/tep/.patched $(SQLITE_DIR)/sqlite3.c
83 cc -O2 -I$(SQLITE_DIR) -c .cache/x86/tep/native/sqlite/tep_sqlite.c -o $@
84
85# arm64: gcc inside the emulated arm64 root (slow: SQLite takes minutes).
86.cache/arm64/libsqlite3.a: $(SQLITE_DIR)/sqlite3.c
87 mkdir -p $(@D)
88 $(ARM64) cc -O2 $(SQLITE_DEFS) -c $< -o .cache/arm64/sqlite3.o
89 $(ARM64) ar rcs $@ .cache/arm64/sqlite3.o
90
91.cache/arm64/tep/tep/sphttp.o: .cache/arm64/tep/.patched
92 $(ARM64) cc -O2 -c .cache/arm64/tep/tep/sphttp.c -o $@
93
94.cache/arm64/tep/native/sqlite/tep_sqlite.o: .cache/arm64/tep/.patched $(SQLITE_DIR)/sqlite3.c
95 $(ARM64) cc -O2 -I$(SQLITE_DIR) -c .cache/arm64/tep/native/sqlite/tep_sqlite.c -o $@
96
97X86_DEPS := .cache/x86/libsqlite3.a .cache/x86/tep/tep/sphttp.o .cache/x86/tep/native/sqlite/tep_sqlite.o
98ARM64_DEPS := .cache/arm64/libsqlite3.a .cache/arm64/tep/tep/sphttp.o .cache/arm64/tep/native/sqlite/tep_sqlite.o
99
100deps: $(X86_DEPS) $(ARM64_DEPS)
101
102# ---- the app ---------------------------------------------------------------
103# tep translates app.rb (writing .app.tep.rb beside it) and runs Spinel.
104dist/app: $(SOURCES) version.rb $(X86_DEPS)
105 mkdir -p dist .cache/x86/tmp
106 TMPDIR=$(abspath .cache/x86/tmp) SPINEL=$(SPINEL_HOST) LIBRARY_PATH=$(abspath .cache/x86) \
107 $(RUBY) .cache/x86/tep/bin/tep build app.rb -o $@
108
109# The host Spinel turns Ruby into C (fast, native); scripts/arm64-cc then
110# compiles and links that C statically inside the arm64 root.
111dist/app-linux-arm64: $(SOURCES) version.rb $(ARM64_DEPS)
112 mkdir -p dist .cache/arm64/tmp
113 TMPDIR=$(abspath .cache/arm64/tmp) SPINEL=$(abspath scripts/spinel-cross) \
114 SPINEL_HOST=$(SPINEL_HOST) SPINEL_ARM64=$(SPINEL_ARM64) \
115 ARM64_WORK=$(abspath .cache/arm64/work) ARM64_LIB_DIR=$(abspath .cache/arm64) \
116 $(RUBY) .cache/arm64/tep/bin/tep build app.rb -o $@
117 file $@ | grep -q 'ARM aarch64.*statically linked'
118
119# ---- the rest ----------------------------------------------------------------
120# The second run collects garbage every few KB, which shakes out values
121# the generated code forgot to root (one such bug is why tep is patched).
122test: dist/app
123 test/run.sh dist/app
124 SPINEL_GC_STRESS=1 test/run.sh dist/app
125
126clean:
127 rm -rf dist .app.tep.rb version.rb .cache/x86/tmp .cache/arm64/tmp .cache/arm64/work
128
129# Every compiled third-party artifact goes; the downloaded SQLite source stays.
130clean-deps: clean
131 rm -rf .cache/x86 .cache/arm64
132
133BUMP_FROM := BUILD_NOTE = "todo-spinel"
134BUMP_TO := BUILD_NOTE = "todo-spinel (bumped)"
135
136bump:
137 grep -qF '$(BUMP_FROM)' app.rb
138 sed -i 's/^$(BUMP_FROM)$$/$(BUMP_TO)/' app.rb
139
140unbump:
141 grep -qF '$(BUMP_TO)' app.rb
142 sed -i 's/^$(BUMP_TO)$$/$(BUMP_FROM)/' app.rb
143
144MESSAGE ?= Deploy todo-spinel $(VERSION)
145
146deploy: dist/app-linux-arm64
147 carlos deploy --account bfj --app todo-spinel --target linux-arm64 --message "$(MESSAGE)" dist/app-linux-arm64
148