-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
191 lines (161 loc) · 9.51 KB
/
Copy pathMakefile
File metadata and controls
191 lines (161 loc) · 9.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
.PHONY: help test boot-test rust-test stage0 stage2 bundle-cli quick-bundle-cli cli playground playground-dev fmt bench bench-guard bench-compare awfy clean npm-pack npm-publish npm-test
STAGE1_WASM ?= target/boot-stage1.wasm
STAGE2_WASM ?= target/boot.wasm
STAGE3_WASM ?= /tmp/twinkle-selfhost/stage3.wasm
STAGE4_WASM ?= /tmp/twinkle-selfhost/stage4.wasm
DENO_BIN ?= deno
TWK_CLI ?= $(DENO_BIN) run --allow-read --allow-write --allow-env tools/js_runtime/deno_main.mjs
# Source file sets — used for dependency tracking.
RUST_SRCS := $(shell find src -name '*.rs') Cargo.toml Cargo.lock
BOOT_SRCS := $(shell find boot -name '*.tw' -not -path 'boot/tests/*' -not -path 'boot/tmp/*' -not -path 'boot/repros/*' -not -path 'boot/prelude/*' -not -path 'boot/stdlib/*')
CORE_LIB_SRCS := $(shell find boot/prelude boot/stdlib -name '*.tw')
help:
@printf 'Twinkle development targets:\n'
@printf ' make test Run Rust, boot compiler, and JS runtime tests\n'
@printf ' make boot-test Run boot compiler test suite\n'
@printf ' make rust-test Run Rust test suite\n'
@printf ' make npm-test Run JS runtime/lib/CLI test suite\n'
@printf ' make stage0 Build the Rust stage0 compiler\n'
@printf ' make stage2 Rebuild target/boot.wasm via self-host loop\n'
@printf ' make bundle-cli Rebuild stage2 payload and build Deno target/twk\n'
@printf ' make cli Alias for bundle-cli\n'
@printf ' make fmt Format boot compiler .tw source files\n'
@printf ' make bench Run the Vector benchmark suite (examples/performance/compiler/)\n'
@printf ' make bench-guard Check vector scaling/bulk-copy guards\n'
@printf ' make bench-compare Compare persistent collections with Clojure\n'
@printf ' make awfy Run the AWFY-style cross-language benchmark suite\n'
@printf ' make playground Build playground from latest published packages (no compiler build)\n'
@printf ' make playground-dev Dev server against the in-repo compiler (TWINKLE_LOCAL)\n'
# Fast day-to-day validation for boot compiler changes.
boot-test: target/twk
target/twk test
rust-test:
cargo test --release
test: rust-test boot-test npm-test
# Build the Rust stage0 compiler used to bootstrap the self-hosted compiler.
# File target so downstream rules rebuild only when Rust sources change.
stage0: target/release/twk
target/release/twk: $(RUST_SRCS)
cargo build --release
# Refresh target/boot.wasm from current boot sources and verify the fixed point.
# Stage0 (Rust) → stage1, stage1 → stage2, stage2 → stage3, stage3 → stage4.
# Compare stage3 == stage4 (both built by boot compilers, avoiding Rust/boot
# encoder divergence in the stage2 vs stage3 comparison).
stage2: $(STAGE2_WASM)
boot/lib/module/core_lib.tw: $(CORE_LIB_SRCS) tools/generate_core_lib.py
python3 tools/generate_core_lib.py
@if [ -x target/twk ]; then \
target/twk fmt boot/lib/module/core_lib.tw; \
else \
printf 'target/twk not available; skipping core_lib formatting\n'; \
fi
$(STAGE2_WASM): $(BOOT_SRCS) $(CORE_LIB_SRCS) boot/lib/module/core_lib.tw target/release/twk tools/js_runtime/runtime.mjs tools/js_runtime/deno_main.mjs tools/js_runtime/node_host.mjs
@printf '\n==> Build stage1 compiler with stage0 -> $(STAGE1_WASM)\n'
./target/release/twk build boot/main.tw -o $(STAGE1_WASM)
@printf '\n==> Build bridge module via stage1\n'
BOOT_WASM=$(STAGE1_WASM) $(TWK_CLI) run boot/tests/gen_bridge_wasm.tw
@printf '\n==> Embed bridge bytes into the JS runtime\n'
node tools/generate_bridge_bytes.mjs
@printf '\n==> Self-hosted project check via stage1\n'
BOOT_WASM=$(STAGE1_WASM) $(TWK_CLI) check
@printf '\n==> Build stage2 compiler with stage1 -> $(STAGE2_WASM)\n'
BOOT_WASM=$(STAGE1_WASM) $(TWK_CLI) build -o $(STAGE2_WASM)
@printf '\n==> Build stage3 compiler with stage2 -> $(STAGE3_WASM)\n'
@mkdir -p $(dir $(STAGE3_WASM))
BOOT_WASM=$(STAGE2_WASM) $(TWK_CLI) build -o $(STAGE3_WASM)
@printf '\n==> Adopt stage3 as stage2 (converge to boot-compiled baseline)\n'
@cp $(STAGE3_WASM) $(STAGE2_WASM)
@printf '\n==> Build stage4 compiler with stage3 -> $(STAGE4_WASM)\n'
BOOT_WASM=$(STAGE2_WASM) $(TWK_CLI) build -o $(STAGE4_WASM)
@printf '\n==> Compare stage3 and stage4 WASM\n'
@cmp -s $(STAGE2_WASM) $(STAGE4_WASM) \
&& printf 'Fixed point reached: stage3 == stage4\n' \
|| { printf 'error: fixed point mismatch; compare files: $(STAGE2_WASM) $(STAGE4_WASM)\n' >&2; exit 1; }
@printf '\nSelf-host loop completed successfully.\n'
# Build the Deno standalone CLI from target/boot.wasm.
target/twk: $(STAGE2_WASM) tools/build_deno_cli.sh tools/js_runtime/runtime.mjs tools/js_runtime/deno_main.mjs tools/js_runtime/node_host.mjs
DENO_BIN="$(DENO_BIN)" tools/build_deno_cli.sh
# Full standalone CLI rebuild: stage2 payload + Deno compile.
bundle-cli: stage2 target/twk
cli: bundle-cli
# Rebuild the standalone CLI from the existing target/boot.wasm without rebuilding
# the self-hosted payload. This is only correct when target/boot.wasm is already fresh.
quick-bundle-cli:
DENO_BIN="$(DENO_BIN)" tools/build_deno_cli.sh
# ---------------------------------------------------------------------------
# Playground
# ---------------------------------------------------------------------------
#
# The playground is a plain Vite app that consumes the published packages
# (@twinkle-lang/twinkle for the compiler runtime + boot.wasm, and
# tree-sitter-twinkle for the grammar wasm + highlight query).
#
# `make playground` builds from the published packages (just npm + vite, no
# Rust/Deno/self-host) — this is what the GitHub Pages deploy runs, so the deploy
# stays cheap. It installs the latest published @twinkle-lang/twinkle +
# tree-sitter-twinkle at build time, so the live site always tracks the newest
# publish with no lockfile bump (publish, then push — done). `--no-save` keeps
# the committed package.json/lock untouched.
#
# `make playground-dev` runs the dev server against the in-repo compiler: it
# builds target/boot.wasm and sets TWINKLE_LOCAL=1 so Vite aliases the package
# specifiers to current in-repo artifacts, letting you test unreleased changes.
# Ensure playground npm deps are installed (pinned; used by playground-dev)
playground/node_modules: playground/package.json playground/package-lock.json
cd playground && npm ci && touch node_modules
# Build from the latest published packages (cheap; no compiler build).
playground:
cd playground && npm install --no-save @twinkle-lang/twinkle@latest tree-sitter-twinkle@latest && npx vite build
# Tree-sitter grammar wasm (rebuild when grammar.js changes; needs Docker)
tree-sitter-twinkle/tree-sitter-twinkle.wasm: tree-sitter-twinkle/grammar.js
cd tree-sitter-twinkle && npx tree-sitter generate && npx tree-sitter build --wasm
# Dev server against the in-repo compiler (TWINKLE_LOCAL aliases to in-repo
# artifacts), so unreleased compiler/runtime changes show up in the playground.
# web.mjs self-loads boot.wasm via `new URL('./boot.wasm', import.meta.url)`, so
# stage it next to web.mjs (the published package ships it flattened). The bridge
# is embedded in runtime.mjs via bridge_bytes.mjs, so no bridge.wasm is staged.
playground-dev: $(STAGE2_WASM) tools/js_runtime/bridge_bytes.mjs tools/js_runtime/runtime.mjs tools/js_runtime/web.mjs tree-sitter-twinkle/tree-sitter-twinkle.wasm playground/node_modules
cp $(STAGE2_WASM) tools/js_runtime/boot.wasm
cd playground && TWINKLE_LOCAL=1 npx vite
# Run the Vector benchmark suite (RRB Gate B baselines). See examples/performance/compiler/README.md.
# Pass BENCH=<name> to run a single benchmark, e.g. `make bench BENCH=concat_prepend`.
BENCH ?=
bench: target/twk
@for f in $(if $(BENCH),examples/performance/compiler/$(BENCH).tw,$(sort $(wildcard examples/performance/compiler/*.tw))); do \
printf '\n==> %s\n' "$$f"; \
target/twk run "$$f" || exit 1; \
done
bench-guard: target/twk
python3 tools/check_vector_scaling.py
bench-compare: target/twk
python3 tools/bench_persistent_compare.py
# Run the AWFY-style cross-language benchmark suite. See examples/performance/awfy/README.md.
awfy: target/twk
@examples/performance/awfy/run.sh
# Format the boot project's reachable modules (project mode over the configured
# entries in twinkle.toml). Note: this excludes the bundled stdlib/prelude
# sources and unreachable trees (bench/, repros/); format those explicitly.
fmt: target/twk
@target/twk fmt
clean:
cargo clean
rm -rf target/boot.wasm target/boot-stage1.wasm target/twk target/deno-assets
# ---------------------------------------------------------------------------
# npm package (@twinkle-lang/twinkle)
# ---------------------------------------------------------------------------
# Stage a self-contained npm package into target/npm/ and build the tarball.
# Depends on a fresh self-hosted payload.
npm-pack: $(STAGE2_WASM) tools/build_npm_pkg.sh tools/npm/package.json tools/npm/README.md $(wildcard tools/js_runtime/*.mjs)
tools/build_npm_pkg.sh
cd target/npm && npm pack
# Publish the staged package to npm (requires `npm login` and the
# @twinkle-lang organization to exist).
npm-publish: $(STAGE2_WASM) tools/build_npm_pkg.sh tools/npm/package.json tools/npm/README.md $(wildcard tools/js_runtime/*.mjs)
tools/build_npm_pkg.sh
cd target/npm && npm publish
# Run the JS runtime/lib/CLI test suite. web.test.mjs reads ./boot.wasm next to
# web.mjs and index.mjs's compile() prefers it, so stage a fresh copy first —
# otherwise a stale playground-dev artifact silently shadows the current build.
npm-test: $(STAGE2_WASM)
cp $(STAGE2_WASM) tools/js_runtime/boot.wasm
node --test tools/js_runtime/*.test.mjs