Regenerates the per-app static-NIF table source files in
priv/generated/driver_tab_ios.zig and priv/generated/driver_tab_android.zig.
These files are linked before libbeam.a so they override BEAM's empty
built-in erts_static_nif_tab[]. Without them, load_nif/2 falls back to
dlopen, which is broken on iOS (App Store rejects bundled .dylibs) and
on Android (RTLDLOCAL hides parent's `enif*` symbols from children).
mix mob.regen_driver_tab # regenerate both platforms (default: Zig)
mix mob.regen_driver_tab --format c # emit driver_tab_*.c instead (hand-editable C)
mix mob.regen_driver_tab --check # verify on-disk matches manifest, exit non-zero on driftFormat
Zig is the default as of Phase 6a iter 4 — it uses comptime gates
instead of #ifdef for guarded NIFs (e.g. iOS sqlite3_nif
device-only), and Zig's export keyword produces the same C-ABI
symbols libbeam.a expects. --format c is still supported for
anyone who wants a hand-editable C dispatch table. Both formats
produce equivalent behavior at link time.
C NIF authors are unaffected by the default: their c_src/<name>.c
files compile via the usual path, and the Zig dispatch table calls
their <name>_nif_init() function through standard C ABI (extern fn <name>_nif_init() callconv(.c)).
Where the NIF list comes from
MobDev.StaticNifs.default_nifs/0 baked-in defaults are merged with any
:static_nifs set in mob.exs:
config :mob_dev,
static_nifs: [
%{module: :my_native, archs: [:all]}
]See MobDev.StaticNifs for the entry schema and arch values.
Why a Mix task and not a build-time generator
The output is committed to the app's repo so reviewers can see what's in
the static-link surface. It also lets non-Mob build tools (e.g. xcodebuild
invoked outside mix mob.deploy) pick up the file as plain source. The
task is fast (deterministic file generation) so re-running it on every
mix compile is cheap.
Drift detection
mob.doctor runs --check mode and reports any drift between the
manifest and the on-disk files. CI can do the same.