All notable changes to nx_tflite_mob are documented here.
Format: Keep a Changelog. Versioning: SemVer.
[0.0.4]
Changed
- Docs rewrite. This release is docs-only — no source-level
changes. Anyone landing on
hexdocs.pm/nx_tflite_mob
can now follow end-to-end without having to ask "is this an Nx
backend?" or "how do I decode the bytes?".
@moduledocrewritten with a clear "this is NOT an Nx backend" lede + per-platform delegate sections (Core ML, NNAPI, XNNPACK, Metal-planned) + explicit input/output byte-layout tables for common models + an "optional Nx interop" section showing how to compose withEMLX.Backend/Nx.from_binary/3if desired.README.mdrewritten as the landing doc. Drops the stale "NIF loads inside Mob's running BEAM ⏸ blocked" status (resolved end-to-end in 0.0.3 via mob_dev's static-NIF integration). Adds "Two ways to use it" —mix mob.enable tflitefor Mob apps vsmake {android,ios_device,ios_sim,mac}for standalone Elixir apps. Per-platform perf table now includes the measured iPhone SE A15 / Moto BXM-8-256 numbers.- New guide:
guides/yolo_walkthrough.md— complete YOLOv8n end-to-end walkthrough from model acquisition to bounding boxes, with the full per-stage timing breakdown that took our Android live-YOLO loop from 0.5 FPS to 3.9 FPS. Includes the pure-BEAM INT8 decoder (130× faster than the equivalent Nx.BinaryBackend decode) and the camera-format choice rationale per platform. - New guide:
guides/delegates.md— picking a delegate per platform. Documents the "INT8 + Core ML doesn't work" trap (0/256 nodes delegate), how to discover NNAPI accelerators on Android, whymtk-neuron_shimNPU loses tomtk-gpu_shimGPU for YOLO-class models (post-processing CPU fallback dominates), and when to pick XNNPACK CPU even when GPU/NPU is available. docs()config now groups extras into "Guides" and "Build recipes" sidebar sections.- Tightened function
@docs onload_module/2,call/2,release_module/1— explicit about input/output byte semantics + error conditions.
Notes
- No code changes. The 0.0.3 NIF binary is bit-identical to the
0.0.4 NIF. Upgrade is a no-op for
mix.lock.
[0.0.3]
Added
- Mac arm64 host build for testing.
make macproducespriv/mac/libtflite_nif.solinked against a locally-builtlibtensorflowlite_c.dylib(since TFLite has no Mac arm64 prebuilt distribution). Configurable viaMAC_TFLITE_DIR(defaults to~/.mob/cache/tflite-2.16.1-mac_arm64). - Test suite:
test/test_helper.exs+test/nx_tflite_mob_test.exswith 16 tests covering module shape + package metadata (smoke tier, always runs) and load_module / call / release_module / opt normalisation (integration tier, auto-skipped when the host NIF isn't built — keepsmix testgreen for users who only deploy to phones). - Test fixture:
test/fixtures/add.bin— a 544-byte TFLite model (output = 3*input, 1×8×8×3 float32) lifted from the upstreamtensorflow/lite/testdata/set. Used by the integration tests to prove the NIF executes a real model end-to-end on the host. docs/build_mac_tflite.md— reproducible recipe for building the Maclibtensorflowlite_c.dylibfrom TF v2.16.1 source via CMake. Documents thestd::abs<T>libc++ patch and theCMAKE_POLICY_VERSION_MINIMUM=3.5env-var workaround for CMake-4 compatibility with TF's oldercmake_minimum_requireddeclarations.
Changed
c_src/tflite_nif.c—__APPLE__branches now refined withTARGET_OS_IPHONE || TARGET_OS_SIMULATORso Mac host builds skip the iOS framework-style headers + Core ML delegate. Mac builds use the same flat-path include layout as Android. No effect on iOS or Android binaries.
Notes
- The Mac build is for host-side testing only. The dylib is not packaged into the Hex release; production phone builds use the prebuilt Android AAR + iOS xcframework as before.
- Tests run automatically in CI on macOS once the dylib is in
~/.mob/cache/. The cache step is a per-CI-runner one-time setup;make macreuses the cache afterwards.
[0.0.2]
Added
- iOS support.
c_src/tflite_nif.cnow compiles forios_device(arm64) andios_sim(arm64) via xcrun, alongside the existing Android arm64 path. The C NIF picks the right delegate per platform:__ANDROID__→ NNAPI (mtk-gpu_shim,mtk-neuron_shim, etc.)__APPLE__→ Core ML (with optionalcoreml_ane_onlyfor devices with an Apple Neural Engine)xnnpack(default) on both
Makefiletargets:make ios_device,make ios_sim,make android,make all_mobile. Each produces a per-archlibtflite_nif.{a,so}underpriv/<target>/.- Framework-style includes on iOS (
<TensorFlowLiteC/c_api.h>resolved via-F-flagged search paths) vs. flat-path includes on Android ("tensorflow/lite/c/c_api.h"resolved via-I).
Measured on real hardware
| Device | Path | Inference |
|---|---|---|
| Moto G Power 5G (BXM-8-256) | NNAPI / mtk-gpu_shim INT8 | 75-117 ms |
| iPhone SE 3rd gen (A15) | Core ML → ANE (FP16 model) | 24 ms |
Notes
- iOS framework binaries (
TensorFlowLiteC.framework/TensorFlowLiteCetc.) ship as Mach-O MH_OBJECT (filetype=1), not MH_DYLIB. The linker pulls them statically into the app's main binary at build time. Do NOT embed them as runtime.frameworkbundles in the.app— it trips iOS install twice (missing per-framework Info.plist, then "code signature version no longer supported" since codesign only produces v3 signatures for MH_EXECUTE/MH_DYLIB). - Integration with the Mob
framework happens via
mix mob.enable tflitein mob_dev ≥ 0.5.8.
[0.0.1] — 2026-05-16
Initial release.
Added
- C NIF wrapping the TensorFlow Lite C API:
load_module/2,call/2,release_module/1. - Android NNAPI delegate support with accelerator selection
(
mtk-gpu_shim,mtk-neuron_shim, etc.). - XNNPACK CPU path (default).
- Standalone Android
benchCLI (scripts/bench_android/bench.c) that hit 155 ms YOLOv8n via NNAPImtk-gpu_shimon the Moto G Power 5G (2024) — the headline that prompted this package's existence.