Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
eb989e7
ci: seed on-device Python runtime from python_build_run_id (android)
ndonkoHenri Jul 12, 2026
c4d60f4
ci: seed on-device iOS runtime too (python_build_run_id)
ndonkoHenri Jul 12, 2026
a53cfea
recipe-tester: ship path-hungry packages extracted to disk (Flet 0.86)
ndonkoHenri Jul 12, 2026
9c6354f
refactor: centralize version variables in meta.yaml for multiple recipes
ndonkoHenri Jul 12, 2026
b659f19
recipe-tester: declare extract_packages in meta.yaml, not a sidecar file
ndonkoHenri Jul 12, 2026
5aef198
recipe-tester: move test-only deps into meta.yaml `test.requires`
ndonkoHenri Jul 12, 2026
25a2f29
forge: ABI-tag bare CPython extension modules in fix_wheel (Android)
ndonkoHenri Jul 12, 2026
25be755
recipe: pysodium + opaque — load bundled lib by soname (Flet 0.86 And…
ndonkoHenri Jul 12, 2026
b2b54a8
recipe: pycryptodome + pycryptodomex — resolve native module via impo…
ndonkoHenri Jul 12, 2026
98b036a
recipe: llama-cpp-python — load bundled libs by soname on Android (Fl…
ndonkoHenri Jul 12, 2026
6186f3a
recipe: jq — static-link libjq so the extension doesn't collide on An…
ndonkoHenri Jul 12, 2026
c87658e
skills: document the Flet 0.86 sitepackages.zip failure class + meta …
ndonkoHenri Jul 12, 2026
24ad035
recipe: selectolax — drop vestigial `modest` namespace import (Flet 0…
ndonkoHenri Jul 12, 2026
b89676b
dev: add default for `PYTHON_BUILD_RUN_ID` if input is empty
ndonkoHenri Jul 12, 2026
fdb7743
recipe: opencv-python — load native cv2 under top-level name on Andro…
ndonkoHenri Jul 12, 2026
d05bf43
recipe: python-magic — ship magic.mgc in-wheel + load from memory (Fl…
ndonkoHenri Jul 12, 2026
87e958e
skills: python-magic 0.86 fix (data file in flet-lib opt/ → ship in-w…
ndonkoHenri Jul 12, 2026
ce098c1
recipe: bump build numbers for 0.86 loader-patch changes (llama-cpp-p…
ndonkoHenri Jul 12, 2026
033cfd8
skills: apsw 0.86 = serious_python _SorefFinder gap (package whose __…
ndonkoHenri Jul 12, 2026
413951c
recipe: jq — gate the static-link syntax per platform (fix iOS build)
ndonkoHenri Jul 12, 2026
af7ad8b
skills: jq iOS -l:NAME.a gotcha (GNU ld only; Apple ld64 needs -lX) —…
ndonkoHenri Jul 12, 2026
7aa573b
ci: temporarily disable concurrency cancel-in-progress (parallel targ…
ndonkoHenri Jul 12, 2026
06f4f71
forge: convert iOS MH_BUNDLE extensions to MH_DYLIB in fix_wheel
ndonkoHenri Jul 12, 2026
b805269
skills: iOS MH_BUNDLE->MH_DYLIB fix (CMake extensions ignore LDSHARED…
ndonkoHenri Jul 12, 2026
d01a269
skills(forge-ci): transitive patched-dep resolves to unpatched publis…
ndonkoHenri Jul 13, 2026
d917c3f
recipe: opencv-python — extend cv2 loader to iOS framework-ized nativ…
ndonkoHenri Jul 13, 2026
9a0667d
skills: opencv iOS cv2 loader (.fwork framework resolution) + iOS-sim…
ndonkoHenri Jul 13, 2026
60ec983
recipe: pyobjus strip py2 examples + pyarrow rebuild for iOS bundle->…
ndonkoHenri Jul 13, 2026
cb2ad99
skills: iOS _posixshmem ModuleNotFoundError (multiprocessing) = pytho…
ndonkoHenri Jul 13, 2026
fb0ec2f
recipe: scikit-learn — drop obsolete ios-guard-multiprocessing-import…
ndonkoHenri Jul 13, 2026
20654f9
recipe: llama-cpp-python — resolve iOS .fwork markers in the ctypes l…
ndonkoHenri Jul 13, 2026
845821d
skills(forge-error-catalogue): sp #223 iOS launch-crash entry (interd…
ndonkoHenri Jul 13, 2026
b408c8a
ci: use python-build 29242819654 (iOS _posixshmem) + serious_python f…
ndonkoHenri Jul 13, 2026
bfef1c0
skills(forge-ci): pre-PR validation against unreleased serious_python…
ndonkoHenri Jul 13, 2026
c974366
recipes: bump ncnn/coolprop/faiss-cpu build numbers for forge iOS MH_…
ndonkoHenri Jul 13, 2026
8e5b7ca
skills(forge-ci): PUSH-before-dispatch trap — --ref checks out the fo…
ndonkoHenri Jul 13, 2026
59357cd
recipes: normalize jq/llama-cpp-python/opencv-python to a single buil…
ndonkoHenri Jul 13, 2026
17a76c0
ci: build recipe-tester APK for x86_64 only + parameterize serious_py…
ndonkoHenri Jul 13, 2026
aaa268b
recipe: llama-cpp-python — extract_packages [llama_cpp] to fix Androi…
ndonkoHenri Jul 13, 2026
0ed3ae7
skills(forge-error-catalogue): ctypes lib trapped in sitepackages.zip…
ndonkoHenri Jul 13, 2026
d1bf8c6
Revert "recipe: llama-cpp-python — extract_packages [llama_cpp] to fi…
ndonkoHenri Jul 13, 2026
0153ea6
recipe: llama-cpp-python — loader falls through to jniLibs bare-sonam…
ndonkoHenri Jul 13, 2026
a81bf90
recipe: llama-cpp-python — accept sys.platform == 'android' in the lo…
ndonkoHenri Jul 13, 2026
56d1e78
skills(forge-error-catalogue): py3.13 sys.platform=='android' loader …
ndonkoHenri Jul 13, 2026
385430f
forge: fix_wheel drops foreign-arch .so + tolerates symbol-versioned …
ndonkoHenri Jul 13, 2026
2ece499
updates
ndonkoHenri Jul 14, 2026
312e5d2
recipe: matplotlib — fix iOS launch SIGSEGV (ft2font static-init GIL)
ndonkoHenri Jul 14, 2026
fbef5db
ci: add publish opt-in to deploy dispatches + bump pymongo/onnxruntime
ndonkoHenri Jul 14, 2026
cdb87c0
update
ndonkoHenri Jul 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion .claude/skills/forge-ci/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,19 @@ Both of these situations are chains — the second is easy to miss:
(onnx's Requires-Dist includes ml_dtypes; ml-dtypes runs as both a package
and a prebuild — that's fine and cheap).

**Silent variant — the dep resolves to an UNPATCHED published copy.** If B is
a *pure-Python* recipe that ALSO exists on pypi.flet.dev/PyPI, A's job won't
error at resolution — it silently pulls the published B (which lacks B's
not-yet-published 0.86 fix) and then fails at **runtime on device** with B's
own loader error, not `No matching distribution`. Seen with opaque →
`pysodium`: opaque's app pulled upstream pysodium, whose `__init__` raised
`ValueError: Unable to find libsodium` (no bare-soname fallback), even though
`flet-libsodium` was prebuilt. Fix: prebuild the **patched dep recipe** too so
its `-9999` wheel wins — `packages="opaque:"
prebuild_recipes="flet-libopaque,flet-libsodium,pysodium"`. Tell: a device
traceback whose failing frame is in a *dependency* package, not the one under
test → that dep is resolving to its unpatched published build.

If a chain dep lives on a *different* branch, merge that branch in first
(`git merge machine/<dep-branch>`) so the recipe dir exists for the prebuild.

Expand Down Expand Up @@ -191,8 +204,31 @@ the log.
| `packages` | `"name:"` entries, comma-separated; `:` suffix means default version. `ALL` expands to every recipe |
| `prebuild_recipes` | comma-separated, **ordered**, built per-job before packages |
| `python_versions` | defaults to all three; narrow for a quick re-run (e.g. `3.12.13`) |
| `mobile_test_pythons` | default `3.12` — leave it; never `ALL` on this fork |
| `mobile_test_pythons` | default `3.12` — leave it; never `ALL` on this fork. Pass `""` to build wheels WITHOUT the on-device test (e.g. when the test can't pass yet because the fix lives in unreleased serious_python — you'll test locally) |
| `archs` | default `android,iOS` |
| `python_build_run_id` | a `flet-dev/python-build` Actions run-id whose artifacts to use instead of the pinned release; empty → the hardcoded FALLBACK in `build-wheels-version.yml` (grep `PYTHON_BUILD_RUN_ID: ${{ … || '<id>' }}`). Bump that fallback to ship an unreleased python-build fix to every job |

## Testing recipes against UNRELEASED serious_python / python-build (pre-PR validation)

When a recipe's green depends on an sp/python-build fix that isn't in a published
release yet (e.g. sp #223 iOS framework relocation, python-build iOS `_posixshmem`),
wire CI + local to the fix so recipes validate BEFORE the PR:
- **python-build fix** → bump the `PYTHON_BUILD_RUN_ID` fallback constant in
`build-wheels-version.yml` to the python-build CI run that has it (verify that run
is `success` and has the `python-darwin-<ver>` / `python-android-<ver>` artifacts).
- **serious_python fix** → add a `[tool.flet.flutter.pubspec.dependency_overrides]`
block to `tests/recipe-tester/pyproject.toml.tpl` with **git** deps for
serious_python + `_darwin` + `_android` + `_platform_interface`, each
`{ git = { url = "…/serious-python.git", ref = "<branch>", path = "src/<pkg>" } }`.
flet merges [tool.flet.flutter.pubspec] via a recursive merge, so the nested git
table passes through to the Flutter pubspec; dart pub clones the branch and runs its
darwin scripts. Mark it TEMPORARY — remove once sp is released. (Local old-Xcode
builds also need `device_info_plus`/`connectivity_plus` pins, but keep those OUT of
the committed template — add post-staging; CI's Xcode doesn't need them.)
- The on-device iOS/APK test in CI still uses PUBLISHED sp, so it can't pass until the
release — dispatch wheel builds with `mobile_test_pythons=""` and verify the recipe
LOCALLY (git or path sp override + local flet-cli + `--python-version 3.12`; see the
local-recipe-testing skill). CI goes green only after the sp/python-build release.

## Watching a run without babysitting

Expand Down
38 changes: 34 additions & 4 deletions .claude/skills/forge-error-catalogue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ description: >-
duplicated patch hunks, iOS flatc MACOSX_BUNDLE, .dylib-vs-.so staging,
libc++_shared, config.sub apple-ios, ctypes "Unable to find ... shared
library", PT_LOAD 16KB alignment, lazy_loader "non-existent stub" crashes
(stripped *.pyi), hidden runtime deps, or a stale on-device cache. Sibling
(stripped *.pyi), the Flet 0.86 Android sitepackages.zip class (NotADirectoryError
on a bundled data file -> extract_packages, untagged native .so
ModuleNotFoundError -> forge ABI-tag, ctypes-by-__file__ loaders -> find_spec /
bare soname, jniLibs lib<pkg>.so name collision -> static-link, a package whose
loader re-imports its own native under a fixed top-level name -> opencv cv2
"missing configuration file: ['config.py']" / "Submodule name should always start
with a parent module name"), hidden runtime deps, or a stale on-device cache. Sibling
of `new-mobile-recipe` (authoring), `native-recipe-bumps` (version bumps),
`local-recipe-testing` (on-device testing), and `forge-ci` (CI triage);
this one is the dedicated error -> fix reference.
Expand Down Expand Up @@ -65,18 +71,42 @@ instead of re-deriving it.
`install_data rename:` / `-include` sanity-check breakage, **build.sh
`cmake: command not found` → `requirements.build`**, **duplicated patch hunks
from concatenated diffs**, iOS `flatc` MACOSX_BUNDLE, **`.dylib` staged under
the `.so` name**, **Apple `MacTypes.h` `Ptr` vs `cv::Ptr` ambiguity** (iOS-only;
the `.so` name**, **iOS `Unsupported mach-o filetype (only MH_OBJECT and
MH_DYLIB can be linked)` → forge `fix_wheel` converts a CMake extension's
`MH_BUNDLE` `.so` to `MH_DYLIB`** (inject `LC_ID_DYLIB` + flip filetype + ad-hoc
re-sign; setuptools/Cython/meson already ship dylib), **Apple `MacTypes.h` `Ptr` vs `cv::Ptr` ambiguity** (iOS-only;
hand-written + gen2.py-generated code), **opencv-5 KleidiCV `armv8-a` on x86_64**
and **hardcoded `CMAKE_SYSTEM_PROCESSOR` → ARM asm on the x86_64 sim** (per-arch
fix), **Rust crate with no `target_os="ios"` backend** (`mac_address`, cfg-gate it).
- **Runtime failures** (device/emulator/simulator) — `libc++_shared.so` not found,
- **Runtime failures** (device/emulator/simulator) — **the Flet 0.86 Android
`sitepackages.zip` class** (its umbrella entry explains "why only now"):
`NotADirectoryError` on a bundled data file → **`extract_packages`** meta field;
untagged native `.so` `ModuleNotFoundError`/"circular import" → **forge `fix_wheel`
ABI-tags `PyInit_*` `.so`**; pycryptodome `Cannot load native module …` →
**`importlib.find_spec().origin`**; llama `FileNotFoundError` / ctypes
`find_library`-None → **bare-soname load from jniLibs**; a top-level extension
colliding with a `flet-lib*` at `lib<pkg>.so` → **static-link (`host_build` +
`-l:lib.a`)**; opencv-python cv2 `missing configuration file: ['config.py']` /
`Submodule name should always start with a parent module name. Parent name:
cv2.cv2` → **load the native under top-level name `cv2` via
`ExtensionFileLoader("cv2", find_spec('cv2.cv2').origin)` + `extract_packages`**;
a runtime DATA file that lives in a sibling `flet-lib*` `opt/` tree (dropped by
`copyOpt`, which copies only `.so`) → python-magic `could not find any valid magic
files!` → **ship the data file in the consumer's own wheel (`script_env`
`{platlib}/opt/…` copy in setup.py + `package_data`) + load from memory
(`importlib.resources` bytes → `magic_load_buffers`)**. Plus: `libc++_shared.so` not found,
**CMake OBJECT-lib not linked into the iOS `.framework` → undefined symbol at
dlopen** (opencv-5 MLAS; green build ≠ loadable — verify with `nm -u`/`otool -L`),
ctypes **"Unable to find … shared library"** (Pattern H loader / lib delivery),
`libssl.so.3`/`libcrypto`/`libsqlite` not found, import-name errors, old version
loaded, **lazy_loader "non-existent stub" (serious_python strips `*.pyi`)**,
**hidden runtime deps** (keras→scipy; device-emulating venv method),
**insightface `root=` PermissionError**.
**insightface `root=` PermissionError**, and **iOS app crashes at launch with a
0-byte `console.log` → `dyld: Library not loaded: @rpath/lib<X>.dylib` for a chain
of interdependent bundled dylibs (pyarrow, llama)** → **serious_python #223**:
reconcile framework install-ids + `@rpath` deps to the dotted-framework paths
(`reconcile_framework_install_names` in darwin scripts; needs an sp release for CI;
local sp fix cc28d13 verified pyarrow 4/4 on-sim).
- **Recipe-tester app failures** — host-build (`pg_config` etc.), pypi.flet.dev
index precedence, "no matching distribution" (incl. **ios-simulator also
resolving the iphoneos wheel**), **sdist-only pure-python dep → pip backtrack**
Expand Down
Loading