Skip to content

[codex] Support project extra static libraries#24

Merged
GenericJam merged 1 commit into
GenericJam:masterfrom
dl-alexandre:codex/project-extra-static-libs
Jun 23, 2026
Merged

[codex] Support project extra static libraries#24
GenericJam merged 1 commit into
GenericJam:masterfrom
dl-alexandre:codex/project-extra-static-libs

Conversation

@dl-alexandre

@dl-alexandre dl-alexandre commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a project-side :extra_static_libs hook to :static_nifs entries so Mob apps can link external per-ABI static archives alongside project NIF archives.

Why

Some project NIFs intentionally declare extern symbols and do not host-link their backing archive. That avoids the host/device archive mismatch during host mix compile, then lets the native app link resolve those symbols against the correct per-ABI archive.

The immediate use case is a Ghostty VT NIF in a Mob app:

  • the Zigler NIF declares extern ghostty_terminal_*
  • host compile succeeds without linking an Android .a
  • the Android app link receives the matching libghostty-vt.a for the active ABI

Changes

  • Extends MobDev.StaticNifs entry validation with :extra_static_libs.
  • Requires concrete per-ABI archive keys (:ios_sim, :ios_device, :android_arm64, :android_arm32, :android_x86_64) instead of broad keys like :android or :all.
  • Appends matching per-ABI archive paths into the existing -Dproject_rust_libs= static-library argument, after project Rust/Zig NIF archives.
  • Emits -D<module>_static=true for guarded project NIFs on only the ABIs where the entry applies.
  • Makes iOS project NIF filtering per-ABI for this build-arg path, so device-only guarded entries do not leak into simulator args.
  • Passes Zigler 0.16's required generated-build flags when re-driving staged Zig NIF builds: erts_include, erl_nif_header, erl_nif_win_path, zigler_priv, and module_root.
  • Resolves Zigler dotfile source paths with match_dot: true, avoiding a fallback that would load the host NIF while deriving module_root.

Validation

  • asdf exec mix format lib/mob_dev/static_nifs.ex lib/mob_dev/native_build.ex test/mob_dev/static_nifs_test.exs test/mob_dev/native_build_test.exs
  • asdf exec mix test test/mob_dev/static_nifs_test.exs test/mob_dev/native_build_test.exs
    • 201 tests passed
  • In devide_mob, pinned this branch plus the Zigler static-NIF branch and ran:
    • asdf exec mix compile
    • asdf exec mix android.native --device R52W90AW7EN
    • asdf exec mix mob.connect --no-iex --device R52W90AW7EN
  • Final Android deploy no longer emits the prior host-load _ghostty_* symbol warning while re-driving Zigler's staged build.
  • On a real SM-T577U (arm64-v8a) tablet, remote NIF smoke passed:
    • nif_new(80, 24, 1000)
    • nif_vt_write("REMOTE_VT_OK 42")
    • nif_snapshot("plain") == "REMOTE_VT_OK 42"

@dl-alexandre dl-alexandre force-pushed the codex/project-extra-static-libs branch 2 times, most recently from 0b9b842 to 92ad577 Compare June 22, 2026 19:47
@dl-alexandre dl-alexandre force-pushed the codex/project-extra-static-libs branch from 92ad577 to 83c5462 Compare June 22, 2026 19:52

@GenericJam GenericJam left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff end-to-end. LGTM — approving.

Verified the one risky change (target_arch: :iosp at native_build.ex:3543): traced on_platform?/2. archs: [:ios] expands to {:ios_sim, :ios_device} and still intersects the singleton platform_archs(:ios_sim), so broad iOS entries keep matching both — no regression. The change's only effect is that archs: [:ios_device] entries become disjoint from {:ios_sim} and correctly stop leaking into simulator args. The per-arch singleton seam was already there for this.

Rest checks out: extra_static_libs is per-platform keyed; the -D<module>_static=true comprehension runs over the already platform-filtered entries (the non-matching-ABI test pins this); validation rejects broad arch keys and non-string paths. CI green, security scans pass, device-verified on real arm64 hardware.

Non-blocking follow-ups (fine to land as-is):

  1. No test covers the iOS sim-vs-device filtering — the riskiest behavioral change here is correct-by-logic but untested. A small project_nif_zig_args(:ios_sim) vs (:ios_device) case asserting a device-only entry doesn't leak into sim would lock it in.
  2. zigler_module_root/2 uses a broad Path.wildcard(cwd <> "/**/" <> basename) — if two files share the basename it takes the first match. It falls back gracefully, so low risk, but worth a comment.
  3. A guarded entry that applies to an ABI but has no extra_static_libs archive for it would surface as undefined symbols at app-link. Consider validating "guard present + applicable ABI ⇒ archive present", or documenting the contract.

@GenericJam GenericJam marked this pull request as ready for review June 23, 2026 02:21
@GenericJam GenericJam merged commit 0714b1a into GenericJam:master Jun 23, 2026
3 checks passed
GenericJam added a commit that referenced this pull request Jun 23, 2026
Ships the merged #24: per-ABI external static-archive linking for project
NIFs that declare extern symbols without host-linking their backing archive,
plus Zigler 0.16 staged-build flags. Patch release so downstream apps pick it up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants