-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
403 lines (345 loc) · 21.1 KB
/
Copy pathMakefile
File metadata and controls
403 lines (345 loc) · 21.1 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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
.PHONY: check hooks analyze analyze-floor platforms lint-shell format \
test test-lean test-web test-web-lean test-guards test-browser-engine \
postcards-example-lean test-example-lean-matrix verify-web-lean \
build-wasm build-wasm-lean regen-bindings clean \
test-example test-example-matrix test-example-macos test-example-device \
test-rust test-example-android test-example-ios test-example-linux \
test-example-windows test-example-web \
verify verify-android verify-ios verify-macos verify-linux \
verify-windows verify-web verify-readme-sizes \
compile-macos compile-ios compile-android compile-linux \
compile-windows compile-wasm compile-natives
# ═══════════════════════════════════════════════════════════════════
# SDK resolution
#
# Uses fvm by default (.fvmrc pins the SDK). Contributors without fvm
# can override: make check DART=dart
# icu_kit is pure Dart — no Flutter dependency anywhere in the gate.
# ═══════════════════════════════════════════════════════════════════
DART ?= fvm dart
FLUTTER ?= fvm flutter
CARGO ?= cargo
TEST_RESULTS_DIR ?= test-results
# GTK check — CI auto-installs, dev gets error with instructions.
define ensure_gtk
@command -v pkg-config >/dev/null && pkg-config --exists gtk+-3.0 || { \
if [ -n "$$CI" ]; then sudo apt-get update -qq && sudo apt-get install -y -qq ninja-build libgtk-3-dev; \
else echo "Error: libgtk-3-dev not found. Run: sudo apt-get install -y ninja-build libgtk-3-dev"; exit 1; fi; }
endef
TIMEOUT := $(if $(CI),--timeout=30x,)
VERBOSE := $(if $(CI),--verbose,)
# ═══════════════════════════════════════════════════════════════════
# § 1 — Gate
# ═══════════════════════════════════════════════════════════════════
#
# make check Full local gate before PR.
check: lint-shell analyze analyze-floor platforms test-guards test test-lean \
test-web test-web-lean test-browser-engine test-example-matrix
# make hooks Activate the repo's git hooks (commit-msg, pre-commit).
# Run once after cloning — they stay dormant otherwise.
# Idempotent.
hooks:
@git config core.hooksPath .githooks
@echo "✓ git hooks active (core.hooksPath → .githooks)"
# ═══════════════════════════════════════════════════════════════════
# § 2 — Analyze
# ═══════════════════════════════════════════════════════════════════
#
# make analyze Dart format + shared Dart core (stamped from whuppi/ci)
# + Rust warnings in our patched lines (both native
# feature configs). Needs the Rust toolchain — the same
# requirement the build hook already imposes.
analyze:
@DART="$(DART)" FLUTTER="$(FLUTTER)" bash tool/analyze.sh
# make analyze-floor Resolve to the OLDEST in-range dependencies and analyze
# the shipped code (lib bin hook). The wide lower bounds
# are only honest if the code analyzes against them, not
# just the newest a fresh build resolves. Static analysis
# only — no native build. Tests are excluded on purpose;
# a consumer sees lib, never your tests. Snapshots and
# restores the lock so a local run leaves the tree clean.
analyze-floor:
@cp pubspec.lock pubspec.lock.floorbak; \
$(DART) pub downgrade >/dev/null && $(DART) analyze --fatal-infos lib bin hook; rc=$$?; \
mv pubspec.lock.floorbak pubspec.lock; \
$(DART) pub get >/dev/null 2>&1 || true; \
exit $$rc
# make platforms Gate pub.dev platform support: pana (the exact analyzer
# pub.dev runs, pinned + radar-tracked) must still report all
# 6 platforms, else a regression like an unconditional
# dart:io/dart:ffi import in the wrong layer silently drops
# web. Shared gate tool/platforms_gate.sh (canonical in
# whuppi/ci, stamped into tool/); PANA_VERSION comes from
# this repo's tool/versions.env.
platforms:
@DART="$(DART)" EXPECTED_PLATFORMS="android ios linux macos windows web" bash tool/platforms_gate.sh
# make lint-shell Shell portability gate: shellcheck + a bash 4.0+ scan
# that catches macOS bash 3.2 breaks in scripts and in
# workflow run: blocks. Stamped from whuppi/ci.
lint-shell:
@bash tool/lint_shell.sh
# make format Format in place (analyze also formats; this is the
# standalone entry). The example and its test_support
# harness are separate packages — format each from its own
# root so `dart format` reads its own resolution.
format:
@$(DART) format lib bin test tool hook
@[ -d example ] && ( cd example && $(DART) format lib test integration_test test_driver ) || true
@[ -d example/test_support ] && ( cd example/test_support && $(DART) format lib ) || true
# ═══════════════════════════════════════════════════════════════════
# § 3 — Test
# ═══════════════════════════════════════════════════════════════════
#
# make test The full VM suite. The build hook compiles icu_capi from
# vendor/icu4x on first run (needs the Rust toolchain);
# incremental cargo caches make later runs fast.
test:
@echo "=== VM suite (build hook compiles icu_capi on first run) ==="
@mkdir -p $(TEST_RESULTS_DIR)
@$(DART) test $(TIMEOUT) --file-reporter json:$(TEST_RESULTS_DIR)/vm.json
# make test-rust Cargo tests for the patched vendored crate — icu_capi is
# where every fork patch lives, so this is the rebase-safety
# harness: upstream's own tests riding the fork prove a patch
# (or a rebase of one) didn't break neighboring behavior.
# Same feature set + no-default-features as the hook's build.
test-rust:
@echo "=== Rust: icu_capi (vendored fork, native features) ==="
cargo test --manifest-path vendor/icu4x/ffi/capi/Cargo.toml \
--no-default-features \
--features "$$(bash tool/compile_rust.sh --features native)"
# make test-lean The LEAN binary end to end: test_fixtures/lean_smoke/ is its own
# hooks root whose pubspec flips bundleCldrData off, so the
# hook builds icu_capi WITHOUT compiled data — proving the
# flavor probe detects it, init fails actionably without
# lazy data, and postcards carry real formatting. The one
# flavor the main suite (always fat) can never exercise.
test-lean:
@echo "=== Lean-binary suite (hook builds the no-CLDR flavor) ==="
@mkdir -p $(TEST_RESULTS_DIR)
@# Explicit pub get first: when `dart test` resolves deps implicitly
@# (fresh checkout, no .dart_tool), the build hook runs but its native
@# asset never reaches the test runtime — every FFI call then dies with
@# "No available native assets". Deterministic; keep the two-step.
@cd test_fixtures/lean_smoke && $(DART) pub get && $(DART) test $(TIMEOUT) --file-reporter json:../../$(TEST_RESULTS_DIR)/lean.json
# make test-guards Mechanical suite rules. Every suite here runs on BOTH
# the VM and Chrome, so a VM-only import in a shared suite
# breaks the browser world silently at load time. dart:io /
# dart:ffi are allowed only in the conditional-import
# corpus loader's VM side (corpus_loader_io.dart) or files that declare
# @TestOn('vm').
test-guards:
@bad=""; \
for f in $$(grep -rlnE "import 'dart:(io|ffi)'" test/ --include="*.dart"); do \
case "$$f" in test/_corpus/corpus_loader_io.dart) continue ;; esac; \
grep -q "@TestOn('vm')" "$$f" || bad="$$bad$$f\n"; \
done; \
if [ -n "$$bad" ]; then \
echo "VM-only import in a two-world suite (add @TestOn('vm') or move"; \
echo "the IO behind the conditional-import loader):"; \
printf "$$bad"; exit 1; fi
@bad=$$(grep -rlnE "import '(package:web/|dart:js_interop)" test/ --include="*.dart" \
| grep -vE "^test/(_corpus/corpus_loader_web|browser_engine/module_probe_web)\.dart$$" \
|| true); \
if [ -n "$$bad" ]; then \
echo "browser-only import outside a conditional-loader web half — every"; \
echo "other suite must compile on the VM:"; \
echo "$$bad"; exit 1; fi
@echo "✓ test guards clean"
# make test-web The same suites in real Chrome (dart test -p chrome).
# Needs web_assets/icu4x.wasm — build once via make build-wasm
# (gitignored artifact; CI provisions it via the wasm-cache /
# wasm-build capabilities).
test-web:
@echo "=== Chrome suite (dart test -p chrome) ==="
@test -f web_assets/icu4x.wasm || { echo "web_assets/icu4x.wasm missing — run: make build-wasm"; exit 1; }
@mkdir -p $(TEST_RESULTS_DIR)
@$(DART) test -p chrome $(TIMEOUT) --file-reporter json:$(TEST_RESULTS_DIR)/web.json
# make test-web-lean The LEAN WASM end to end in real Chrome — the web
# half of what test-lean proves for native. Prepares
# test_fixtures/lean_smoke/web_mirror/ (bindings tree + the
# lean wasm under the standard icu4x.wasm name — the
# exact layout `setup --lean` installs) and runs the
# lean_smoke chrome suite against it. Needs
# web_assets/icu4x-lean.wasm — built by the
# build-wasm-lean dependency when missing.
test-web-lean: build-wasm-lean
@echo "=== Lean-WASM Chrome suite ==="
@rm -rf test_fixtures/lean_smoke/web_mirror
@mkdir -p test_fixtures/lean_smoke/web_mirror
@cp web_assets/diplomat.config.mjs test_fixtures/lean_smoke/web_mirror/
@cp -R web_assets/lib test_fixtures/lean_smoke/web_mirror/lib
@cp web_assets/icu4x-lean.wasm test_fixtures/lean_smoke/web_mirror/icu4x.wasm
@cp test/_corpus/postcards/en_minimal.postcard test_fixtures/lean_smoke/web_mirror/
@mkdir -p $(TEST_RESULTS_DIR)
@cd test_fixtures/lean_smoke && $(DART) test -p chrome $(TIMEOUT) --file-reporter json:../../$(TEST_RESULTS_DIR)/web-lean.json
# make test-browser-engine The browser Intl engine end to end in real
# Chrome — no ICU4X wasm blob, the app's classes
# served off globalThis.Intl (ECMA-402). Runs the VM
# drift guard (the shim's completeness radar) AND the
# per-family behavior suites under BOTH web compilers:
# dart2js AND dart2wasm. The shim is pure js_interop,
# which can compile clean yet diverge at RUNTIME
# between the two compilers (e.g. how a Symbol property
# key marshals), so the suite runs on each. A build-
# only wasm check would miss that class of bug.
test-browser-engine:
@echo "=== Browser Intl engine suite (VM guard + Chrome dart2js + dart2wasm) ==="
@mkdir -p $(TEST_RESULTS_DIR)
@$(DART) test -p vm -p chrome -c chrome:dart2js -c chrome:dart2wasm $(TIMEOUT) test/browser_engine/ --file-reporter json:$(TEST_RESULTS_DIR)/browser-engine.json
# ═══════════════════════════════════════════════════════════════════
# § 3b — Example app (journeys + integration smoke + release verify)
# ═══════════════════════════════════════════════════════════════════
#
# make test-example Host-VM journeys + the macOS integration smoke.
# make test-example-matrix Host-VM journeys: the four tabs driven end to
# end through the real engine, across every
# device profile. No device needed. In `check`.
# make test-example-macos Integration smoke on macOS (real library).
# make test-example-device Integration smoke on DEVICE=<id>.
# make test-example-<plat> Integration smoke on one real target — CI's
# full-test runs each (android/ios/linux/windows/web).
# make verify-<plat> Release build of the example — proves the build
# hook links for that target (incl. Android's
# 16 KB page size).
#
# The example builds icu_capi from vendor/icu4x for its OWN build output on
# first run (needs the Rust toolchain), separate from the package's cache.
DEVICE ?=
test-example: test-example-matrix test-example-macos
test-example-matrix:
@echo "=== Example journeys (host VM, real engine, every device) ==="
@mkdir -p $(TEST_RESULTS_DIR)
@cd example && $(FLUTTER) test $(VERBOSE) $(TIMEOUT) test/journeys --file-reporter json:../$(TEST_RESULTS_DIR)/example-matrix.json
test-example-macos:
@cd example && $(FLUTTER) test $(TIMEOUT) integration_test/icu_kit_smoke_test.dart -d macos
test-example-device:
@cd example && $(FLUTTER) test $(TIMEOUT) integration_test/icu_kit_smoke_test.dart -d $(DEVICE)
test-example-android:
@mkdir -p $(TEST_RESULTS_DIR)
@cd example && $(FLUTTER) test $(VERBOSE) $(TIMEOUT) integration_test/icu_kit_smoke_test.dart --file-reporter json:../$(TEST_RESULTS_DIR)/int-android.json
test-example-ios:
@mkdir -p $(TEST_RESULTS_DIR)
@cd example && $(FLUTTER) test $(VERBOSE) $(TIMEOUT) integration_test/icu_kit_smoke_test.dart --file-reporter json:../$(TEST_RESULTS_DIR)/int-ios.json
test-example-linux:
$(call ensure_gtk)
@mkdir -p $(TEST_RESULTS_DIR)
@cd example && $(FLUTTER) test $(VERBOSE) $(TIMEOUT) integration_test/icu_kit_smoke_test.dart -d linux --file-reporter json:../$(TEST_RESULTS_DIR)/int-linux.json
test-example-windows:
@mkdir -p $(TEST_RESULTS_DIR)
@cd example && $(FLUTTER) test $(VERBOSE) $(TIMEOUT) integration_test/icu_kit_smoke_test.dart -d windows --file-reporter json:../$(TEST_RESULTS_DIR)/int-windows.json
# Web needs the WASM + JS bindings copied into example/web via the
# consumer setup executable; build-wasm produces the artifact first.
test-example-web: build-wasm
@cd example && $(FLUTTER) pub get && $(FLUTTER) pub run icu_kit:setup --force web
@./tool/run_web_test.sh $(FLUTTER)
# ── Verify: release builds of the example ──
verify: verify-android verify-ios verify-macos verify-linux verify-windows verify-web verify-web-lean
verify-android:
@cd example && $(FLUTTER) build apk --release
@bash tool/check_alignment.sh example/build/app/outputs/flutter-apk/app-release.apk
verify-ios:
@cd example && $(FLUTTER) build ios --release --no-codesign
verify-macos:
@cd example && $(FLUTTER) build macos --release
verify-linux:
$(call ensure_gtk)
@cd example && $(FLUTTER) build linux --release
verify-windows:
@cd example && $(FLUTTER) build windows --release
verify-web: build-wasm
@cd example && $(FLUTTER) pub get && $(FLUTTER) pub run icu_kit:setup --force web
@cd example && $(FLUTTER) build web --release
# ═══════════════════════════════════════════════════════════════════
# § 3c — Lean example (example_lean/ — the app under the LEAN binary)
# ═══════════════════════════════════════════════════════════════════
#
# example_lean/ is a build-config shell: its pubspec flips bundleCldrData
# off (so the hook builds the no-CLDR binary) and re-runs example/'s code
# + shared suites. It needs asset postcards to feed the lean binary —
# generated on demand (markers=all is ~7 MB/locale, far too big to
# commit), gitignored. These lanes are CI + on-demand, NOT in the fast
# `check` (slicing every locale is minutes of datagen).
#
# make postcards-example-lean Slice the journey/smoke locale set into
# example_lean/assets/icu/.
# make test-example-lean-matrix Host-VM journeys on the LEAN binary —
# the preload UX + postcard path proven live.
# make verify-web-lean The full web consumer story: clean →
# setup --lean → build web, with postcards.
# Locale union the journeys + smoke format under. Sliced with the `kit`
# preset (every facade family the showcase exercises: format + text +
# locale), NOT `all` — `kit` drops the non-Gregorian calendars and time
# zones the example never touches.
LEAN_EXAMPLE_LOCALES := und,en,en-US,de,fr,hi,ja,ar,th,sv,tr,zh-Hant
postcards-example-lean:
@echo "=== Slicing postcards for example_lean (markers=kit) ==="
@# example_lean is a Flutter app (integration_test etc.), so resolve + run
@# the slice tool through Flutter — bare `dart run` can't see the Flutter SDK
@# deps and fails pub resolution. Matches every other example_lean target.
@cd example_lean && $(FLUTTER) pub get && $(FLUTTER) pub run icu_kit:slice \
--locales=$(LEAN_EXAMPLE_LOCALES) --markers=kit --per-locale --out=assets/icu
test-example-lean-matrix: postcards-example-lean
@echo "=== Lean example journeys (host VM, no-CLDR binary + postcards) ==="
@mkdir -p $(TEST_RESULTS_DIR)
@cd example_lean && $(FLUTTER) pub get && $(FLUTTER) test $(VERBOSE) $(TIMEOUT) \
test/journeys --file-reporter json:../$(TEST_RESULTS_DIR)/example-lean-matrix.json
verify-web-lean: build-wasm-lean postcards-example-lean
@cd example_lean && $(FLUTTER) pub get && $(FLUTTER) pub run icu_kit:setup --lean --force web
@cd example_lean && $(FLUTTER) build web --release
# Measures the real artifacts (postcards via datagen, wasm raw+gzipped,
# hook-built cdylibs) and fails if any size number in README.md doesn't
# match reality. Slow (datagen runs) — on demand + release checklist,
# not in `check`.
verify-readme-sizes:
@$(DART) run tool/verify_readme_sizes.dart
# ═══════════════════════════════════════════════════════════════════
# § 4 — Build + Compile (release pipeline — one target per CI job)
# ═══════════════════════════════════════════════════════════════════
#
# make build-wasm Rebuild web_assets/icu4x.wasm + the JS bindings
# (nightly Rust + wasm-opt; see tool/build_wasm.dart).
# make build-wasm-lean web_assets/icu4x-lean.wasm — the no-CLDR variant
# (~2 MB vs ~19 MB). Skips when already built;
# delete the artifact to force a rebuild.
# make regen-bindings Regenerate the Diplomat Dart/JS bindings inside
# vendor/icu4x after editing a capi patch.
#
# make compile-macos macOS arm64 + x64 (bundled + lean variants each).
# make compile-ios iOS device + simulators (static, nightly).
# make compile-android Android arm64, arm, x64, x86 (needs the NDK).
# make compile-linux Linux x64 + arm64 (cross-compile).
# make compile-windows Windows x64 + arm64 (MSVC).
# make compile-wasm WASM via tool/build_wasm.dart.
# make compile-natives All native targets the host can build.
#
# The release workflow runs one compile-* per CI job with
# COMPILE_OUTPUT_DIR=out and uploads out/ as release assets — the
# hash-verified binaries the build hook downloads for consumers.
compile-macos:
bash tool/compile_rust.sh macos
compile-ios:
bash tool/compile_rust.sh ios
compile-android:
bash tool/compile_rust.sh android
compile-linux:
bash tool/compile_rust.sh linux
compile-windows:
bash tool/compile_rust.sh windows
compile-wasm:
DART="$(DART)" bash tool/compile_rust.sh wasm
compile-natives:
bash tool/compile_rust.sh native
build-wasm:
@$(DART) run tool/build_wasm.dart
build-wasm-lean:
@if [ -f web_assets/icu4x-lean.wasm ]; then \
echo "web_assets/icu4x-lean.wasm present — skipping (delete it to rebuild)"; \
else \
$(DART) run tool/build_wasm.dart --lean; \
fi
regen-bindings:
@$(DART) run tool/regen_bindings.dart
clean:
@rm -rf .dart_tool web_assets/icu4x.wasm web_assets/icu4x-lean.wasm \
test_fixtures/lean_smoke/web_mirror test_fixtures/lean_smoke/.dart_tool $(TEST_RESULTS_DIR)
@echo "✓ clean (vendor cargo caches left intact — cargo clean inside vendor/icu4x if you really mean it)"