iOS release: compile + link activated-plugin NIFs#36
Merged
Conversation
The release path (release.ex/release_device.sh) hand-compiled a fixed object list and never touched plugins, so any app with NIF plugins failed to link: driver_tab_ios references each activated plugin's <module>_nif_init but nothing defined them (iOS statically links all NIFs — no dlopen). The dev path already compiles them via build.zig -Dplugin_c_nifs; this brings the release path to parity. release_env/2 now emits MOB_PLUGIN_IOS_NIF_SOURCES + MOB_PLUGIN_IOS_FRAMEWORKS from MobDev.Plugin.activated() (via the pure, tested plugin_ios_build_env/1). release_device.sh compiles each source with -DSTATIC_ERLANG_NIF_LIBNAME=<basename> (-> <basename>_nif_init) and -fmodules (framework autolink), links the objects, and passes the declared frameworks explicitly. Verified: Sloppy Joe's 10 ObjC NIF plugins compile + link; the IPA code-signs and validates against its App Store profile. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MobDev.Release.HelpersTest's git fixture ran git init/add/commit without clearing the ambient git environment. When the suite runs inside a git hook (.githooks/pre-push), git exports GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE into the env; the fixture inherited them and operated on the outer repo instead of its tmpdir (git add matched nothing -> git commit exited non-zero -> setup crashed, failing both tests). Passed standalone, failed only on push. Clear the leaking vars (nil removes them for the child) on all three git commands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GenericJam
added a commit
that referenced
this pull request
Jul 8, 2026
The iOS release path now compiles + links activated-plugin NIFs (#36), so multi-plugin apps can build a store-ready IPA. Also fixes a git-fixture flake that failed only inside git hooks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
mix mob.release --iosproduced a binary that failed to link for any app with NIF plugins:iOS statically links every NIF into the single app binary (no
dlopenunder the App Store sandbox), sodriver_tab_ios.creferences each activated plugin's<module>_nif_init. The dev path (build.zig -Dplugin_c_nifs, fed byMobDev.Plugin.Merge.nif_sources/2) compiles those in — but the release path (release.ex→release_device.sh) is a separate hand-rolled script that predates plugin support and compiled a fixed object list, never touching plugins. Android was unaffected (per-ABI.sos, not one static binary).Surfaced shipping Sloppy Joe (10 capability plugins) to the App Store.
Fix
Bring the release path to parity.
release_env/2emits two env vars fromMobDev.Plugin.activated()via the pure, unit-testedRelease.plugin_ios_build_env/1:MOB_PLUGIN_IOS_NIF_SOURCES— each activated plugin's iOS C/ObjC NIF source (Merge.nif_sources(activated, :ios))MOB_PLUGIN_IOS_FRAMEWORKS— the union of declared frameworks (Merge.ios_frameworks/1)release_device.shloops over the sources, compiling each with-DSTATIC_ERLANG_NIF_LIBNAME=<basename>(→<basename>_nif_init, matching the table) and-fmodules(Clang autolinks every@imported framework — plugins often import beyond their manifest set, e.g. Accelerate). Objects join the swiftc link line; declared frameworks are passed explicitly.Verified
Sloppy Joe's 10 ObjC NIF plugins compile + link; the resulting
.ipacode-signs and validates against its App Store distribution profile (valid on disk,satisfies its Designated Requirement).Tests
plugin_ios_build_env/1— pure matrix (none / one / many / platform-filtered) inrelease_test.exsrelease_script_test.exs— script-shape assertions (compile loop, libname derivation,$PLUGIN_OBJSon the link, framework flags) so a regression is caught atmix test, not a TestFlight round tripAlso (2nd commit) — a pre-existing test-infra bug
MobDev.Release.HelpersTest's git fixture didn't clear the ambient git env. Inside a git hook (.githooks/pre-push), git exportsGIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE; the fixture inherited them and operated on the outer repo →git commitexited non-zero → setup crashed. Passed standalone, failed only on push. Now cleared on all three git commands.Scope / follow-up
Covers
nif_sources(lang: :c | :objc) +ios_frameworks— what every current plugin uses. The dev path also handles pluginswift_filesand:cpp_archivestatic archives (e.g. mob_nx_eigen); the release path does not yet (no shipped plugin needs them on iOS today). Documented indecisions/2026-07-07-ios-release-links-plugin-nifs.md.🤖 Generated with Claude Code