mob_nx_eigen
Eigen-backed CPU Nx backend, packaged as a mob plugin.
This is the always-available baseline for on-device numerics. Eigen is a header-only C++ template library (NEON-vectorised on ARM), so it needs no GPU and runs anywhere mob runs — iOS and Android, any chip. GPU-accelerated backends (Vulkan, MLX, TFLite) layer on top where a device supports them; NxEigen is the fallback that always works.
How it's built
The NIF is a C++ :cpp_archive plugin contribution: mob_dev's
MobDev.Plugin.CppArchive cross-compiles it to libnx_eigen.a per target ABI
and static-links it into the app's single signed native binary (required —
Android RTLD_LOCAL hides the BEAM's enif_* symbols from a separately-loaded
.so, and iOS forbids dlopen). It references NxEigen's own NIF source + Fine
headers straight from its deps ({:dep, …} tokens) and ships the Eigen-FFT
bridge itself (c_src/).
Eigen headers are fetched at compile time by the bundled eigen_headers Mix
compiler into eigen-3.4.0/ (gitignored) — the published nx_eigen hex package
downloads Eigen in its own Makefile and ships a precompiled .so, so a clean
mix deps.get has no Eigen for the source cross-compile to reference. Set
EIGEN_DIR to a local Eigen 3.4.0 checkout to skip the download.
Android ABI:
cpp_archivetargets arm64/arm32 (+ iOS), not thex86_64Android emulator — build/deploy to an arm device (or dropx86_64from your app'sabiFilters+ build.zig). Building x86_64 with this plugin fails the link with an unresolvednx_eigen_nif_init.
Requires a mob_dev with cpp_archive + the ANDROID_HOME-aware NDK resolution
(≥ the release carrying MOB-89).
Use
# mix.exs
{:mob_nx_eigen, "~> 0.1"}
# mob.exs
config :mob, :plugins, [:mob_nx_eigen]
The plugin's lifecycle.on_start calls MobNxEigen.configure/0 at app boot,
which makes NxEigen.Backend the global Nx backend (falling back to
Nx.BinaryBackend if the NIF can't load).
Status
Replaces the bespoke nxeigen hooks that used to live in mob_dev core
(mix mob.enable nxeigen). Device verification on Android/iOS pending.