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?".
    • @moduledoc rewritten 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 with EMLX.Backend / Nx.from_binary/3 if desired.
    • README.md rewritten 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 tflite for Mob apps vs make {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, why mtk-neuron_shim NPU loses to mtk-gpu_shim GPU 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 on load_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 mac produces priv/mac/libtflite_nif.so linked against a locally-built libtensorflowlite_c.dylib (since TFLite has no Mac arm64 prebuilt distribution). Configurable via MAC_TFLITE_DIR (defaults to ~/.mob/cache/tflite-2.16.1-mac_arm64).
  • Test suite: test/test_helper.exs + test/nx_tflite_mob_test.exs with 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 — keeps mix test green 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 upstream tensorflow/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 Mac libtensorflowlite_c.dylib from TF v2.16.1 source via CMake. Documents the std::abs<T> libc++ patch and the CMAKE_POLICY_VERSION_MINIMUM=3.5 env-var workaround for CMake-4 compatibility with TF's older cmake_minimum_required declarations.

Changed

  • c_src/tflite_nif.c__APPLE__ branches now refined with TARGET_OS_IPHONE || TARGET_OS_SIMULATOR so 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 mac reuses the cache afterwards.

[0.0.2]

Added

  • iOS support. c_src/tflite_nif.c now compiles for ios_device (arm64) and ios_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 optional coreml_ane_only for devices with an Apple Neural Engine)
    • xnnpack (default) on both
  • Makefile targets: make ios_device, make ios_sim, make android, make all_mobile. Each produces a per-arch libtflite_nif.{a,so} under priv/<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

DevicePathInference
Moto G Power 5G (BXM-8-256)NNAPI / mtk-gpu_shim INT875-117 ms
iPhone SE 3rd gen (A15)Core ML → ANE (FP16 model)24 ms

Notes

  • iOS framework binaries (TensorFlowLiteC.framework/TensorFlowLiteC etc.) 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 .framework bundles 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 tflite in 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 bench CLI (scripts/bench_android/bench.c) that hit 155 ms YOLOv8n via NNAPI mtk-gpu_shim on the Moto G Power 5G (2024) — the headline that prompted this package's existence.