Cross-compiles tflite_nif.c (the NIF wrapping TensorFlow Lite's C API)
for one Android or iOS target ABI and archives the result as
libtflite_nif.a. The archive gets static-linked into the user app's
main native binary alongside crypto.a, libemlx.a, and any other
static NIFs.
Companion bits
- Native libs —
MobDev.TfliteDownloaderfetches the TFLite native libraries (AAR for Android, xcframework tarball for iOS) and supplies headers + the runtime library that gets linked into the launcher binary alongside this archive. - C source —
tflite_nif.cships in the:nx_tflite_mobHex dep (the user adds{:nx_tflite_mob, ...}to theirmix.exswhen they runmix mob.enable tflite). This module looks it up via:code.lib_dir(:nx_tflite_mob). - Static-NIF table entry —
:tflite_nifis registered inMobDev.StaticNifs.default_nifs/0with guardMOB_STATIC_TFLITE_NIF. The guard threads intobuild_device.zigastflite_staticand is set totruewhen the project enables this feature.
Why static-link this NIF?
Same constraints as every other NIF mob ships on phones:
- Android.
dlopen'd children inheritRTLD_LOCAL, hiding the parent'senif_*symbols from a separately-loadedlibtflite_nif.so.on_loadthen fails with "cannot locate symbol". Static linking sidesteps that — BEAM findstflite_nif_nif_initviadlsym(RTLD_DEFAULT)against the main app binary. - iOS. App Store forbids loading unsigned dylibs /
dlopen; every NIF must already be present in the signed binary.
The TFLite runtime itself (libtensorflowlite_jni.so on Android,
TensorFlowLiteC.framework on iOS) IS allowed to load via the normal
dynamic-linker path: it's code-signed (iOS) or part of the standard
jniLibs/ contract (Android). Only the NIF init has to be static.
Per-target deltas
| Target | Source | Compiler | nm symbol |
|---|---|---|---|
| android_arm64 | NDK aarch64 clang | aarch64 cross | tflite_nif_nif_init |
| android_arm32 | NDK arm clang | arm cross (armv7-a) | tflite_nif_nif_init |
| ios_sim | xcrun iphonesimulator | arm64-apple-ios-simulator | _tflite_nif_nif_init |
| ios_device | xcrun iphoneos | arm64-apple-ios | _tflite_nif_nif_init |
STATIC_ERLANG_NIF_LIBNAME
We pass -DSTATIC_ERLANG_NIF_LIBNAME=tflite_nif to make ERL_NIF_INIT
emit symbol tflite_nif_nif_init. That matches the convention used by
MobDev.NxEigenNif (nx_eigen → nx_eigen_nif_init) and what
MobDev.StaticNifs.init_fn/1 derives for the :tflite_nif module
entry.
Summary
Functions
Base CFLAGS shared across all targets. Public for testing.
Compile + archive + verify libtflite_nif.a for one target.
Assemble full CFLAGS for a target plus include / framework search paths.
Per-target spec. Public for testing.
All known TFLite NIF targets.
Functions
@spec base_cflags() :: [String.t()]
Base CFLAGS shared across all targets. Public for testing.
@spec build( atom(), keyword() ) :: {:ok, map()} | MobDev.Release.Errors.t()
Compile + archive + verify libtflite_nif.a for one target.
Options:
:nx_tflite_mob_dir— path to the:nx_tflite_mobHex dep (the dir containingc_src/tflite_nif.c). Required.:tflite_dir— path returned byMobDev.TfliteDownloader.ensure/1for this target. Required.:erts_include— per-targeterts-VSN/include/dir. Required.:out_dir— where the archive + object subdir get written. Required.:ndk_root— Android NDK root (Android targets only; defaults to~/Library/Android/sdk/ndk/<NdkVersion.effective()>).
@spec cflags( %MobDev.TfliteNif.Target{ extra_cflags: term(), id: term(), nm_symbol: term(), tools_fn: term() }, [Path.t()], [Path.t()] ) :: [String.t()]
Assemble full CFLAGS for a target plus include / framework search paths.
includes are -I-prefixed; frameworks are -F-prefixed (iOS only —
ignored on Android targets). Order is preserved.
@spec target_spec(atom()) :: %MobDev.TfliteNif.Target{ extra_cflags: term(), id: term(), nm_symbol: term(), tools_fn: term() }
Per-target spec. Public for testing.
@spec targets() :: [atom()]
All known TFLite NIF targets.