Skip to content

Releases: GenericJam/mob_dev

0.5.17

03 Jun 16:54
0b732b6

Choose a tag to compare

Fixed

  • iOS simulator deploy now boots from a clean mix mob.deploy --native (was device-only). Three gaps made the sim deploy incomplete vs the device path, so the sim crashed on boot even though the device worked:
    • The Elixir-distribution apps elixir/logger were staged only under lib/<app>/ebin, which the sim's mob_beam.m doesn't add to the code path — boot failed at ensure_all_started(:elixir) with "elixir.app not found". They're now flattened into the flat BEAMS_DIR alongside eex (which already needed this), where the path resolves.
    • priv/ was only partially staged (repo/migrations), so Application.app_dir(:<app>, "priv/cacerts.pem") was :enoent and Mob.Certs.load_cacerts! crashed the boot. The whole priv/ is now rsynced into the flat dir (cacerts, mix/hex ebins, vendored static, …), matching the device release.
    • Paths.sim_runtime_dir/0 fell back to /tmp/otp-ios-sim for zig-based projects (no ios/build.sh), but the runtime is synced to ~/.mob/runtime/ios-sim — so the launcher and staging disagreed. It now recognizes ios/build.zig and returns the default runtime dir.
      Verified: a clean mob.deploy --native to an iPhone 11 Pro Max sim boots Io, Phoenix endpoint up, embedded Livebook home renders — no manual runtime fixups.

0.5.16

02 Jun 08:04
7873c59

Choose a tag to compare

Fixed

  • Gate the plugin flags on the iOS device build path too. 0.5.15 gated the plugin-flag emission for Android and the iOS simulator build, but zig_build_binary_ios_device still emitted -Dplugin_swift_files/-Dplugin_frameworks (and generated the bootstrap, making plugin_swift_files always non-empty) unconditionally — so mix mob.deploy --native to a physical iPhone broke on an app scaffolded before the plugin system (invalid option: -Dplugin_swift_files). The device path now mirrors the sim path: bootstrap + flags only when plugins are activated. Verified mix mob.deploy --native to a physical iPhone — full OTP, Phoenix endpoint up, LiveView connected, embedded Livebook home rendered.

0.5.15

02 Jun 07:34
f62e566

Choose a tag to compare

Fixed

  • mix mob.release --android --no-slim now actually ships the full OTP tree. The Android release stripped OTP libs unconditionally (OtpAssetBundle.build/2 was called with no opts), so --no-slim was silently ignored on Android. slim is now threaded build_aab → OtpAssetBundle.build(slim:); with slim: false the OTP tree ships untouched. Required for apps that run arbitrary user code at runtime (e.g. an embedded Livebook host doing Mix.install) — stripping any OTP lib (inets, ssl, xmerl, runtime_tools, …) is a latent crash when a user's deps need it. Default stays slim: true.
  • iOS --no-slim release passes App Store validation. The always-on Apple-policy strip cleared erts-*/bin and priv/bin but missed standalone executables inside OTP libs (e.g. erl_interface/bin/erl_call), which App Store validation rejects (90171). Now lib/*/bin/* executables are stripped too (always on), keeping every lib's .beam/.app — so a full-OTP --no-slim bundle is still Apple-compliant.
  • Native builds no longer break on pre-plugin app scaffolding. native_build.ex emitted -Dplugin_c_nifs/-Dplugin_zig_nifs/-Dplugin_jni_sources (Android) and -Dplugin_swift_files/-Dplugin_frameworks (iOS) unconditionally, but an app scaffolded before the plugin system has no such options in its build.zig and Zig rejects the unknown -D flag. These flags (and the iOS plugin bootstrap) are now emitted only when plugins are activated; a plugin-aware build.zig defaults them to "" so behaviour is unchanged there.

0.5.14

02 Jun 05:55

Choose a tag to compare

Fixed

  • iOS release: erl_errno_id_unknown shim written with a literal \n. The weak-stub line in release_device.sh used printf '%s\\n' inside the ~S (raw) heredoc, so bash received both backslashes and printf wrote a literal backslash-n into erl_errno_id_compat.c — clang then rejected the trailing }\n and mix mob.release --ios failed. Now printf '%s\n' (one backslash) emits a real newline. Regression guard added to release_script_test.
  • iOS release: clear preflight when priv/generated/driver_tab_ios.c is missing. The release links a per-app static-NIF driver table, but the dev build uses the built-in Zig table and mix mob.regen_driver_tab defaults to Zig, so a project that never ran it with --format c died deep in release_device.sh with a cryptic cc: no such file. build_ipa now fails early with the exact command to run (mix mob.regen_driver_tab --format c).

0.5.13

30 May 20:39

Choose a tag to compare

Fixed

  • iOS deploy now ships the whole priv/, not just priv/repo/migrations + priv/static. MobDev.Release's iOS bundler copied only migrations and priv/static, so apps that bundle extra runtime assets under priv/:mix/:hex ebins for on-device Mix.install, or a vendored library's own priv/ (e.g. Livebook's priv/static + priv/livebook) — silently never reached the device. Now rsyncs all of priv/, matching the Android deployer. Unblocks on-device Mix.install and embedded Livebook on iOS. Verified on a physical iPhone: priv/mix/ebin (103 beams) and priv/livebook/static present on device, embedded Livebook serves, and Mix.install([{:short_uuid, "~> 0.1"}]) returns :ok.

0.5.12

29 May 22:58

Choose a tag to compare

Changed

  • OTP runtime bumped to 7d46fdd4 (Elixir 1.20.0-rc.5). @otp_hash now points at the otp-7d46fdd4 release: all four platform tarballs (ios-sim, ios-device, android, android-arm32) bundle Elixir 1.20.0-rc.5 matched to the OTP-29 erts. Completes the 1.19.5 to 1.20 runtime migration the bundled-versions manifest was already staged for. Verified end-to-end on a physical iPhone and a physical Android (Moto G): System.version 1.20.0-rc.5, OTP 29, Mix.install([{:short_uuid, "~> 0.1"}]) returns :ok with the dep compiled on-device.

Fixed

  • iOS {spawn, <linked-in driver>} now works (erts erts_open_driver). The iOS-build #ifdef __IOS__ guard returned BADARG for any open_port whose spawn_type included the EXECUTABLE bit (i.e. plain {spawn, Name}), firing before the linked-in-driver name lookup. This broke ram_file ({spawn, "ram_file_drv"}), and therefore file:open(_, [:ram]), erl_tar in-memory extract, hex_tarball.unpack, and Mix.install on iOS. The guard now fires only when no linked-in driver matched the name. Bundled in the 7d46fdd4 OTP tarballs.

0.5.11

20 May 17:39

Choose a tag to compare

Added

  • mob.exs :project_swift_sources config key — optional list of extra Swift sources to compile into the iOS app module alongside Mob's bridge sources. Threaded into both zig_build_binary_ios_sim and zig_build_binary_ios_device as -Dproject_swift_sources=<absolute,paths>. Comma-containing entries are rejected at the boundary; nil/[] is a no-op. Pairs with mob_new's project_swift_sources build hook (mob_new#5). Originally proposed by @dl-alexandre.

0.5.10

19 May 02:15

Choose a tag to compare

Added

  • mix mob.deploy --dist-port N and --node-suffix S flags — manual
    override path for the BEAM-distribution surface. When set, all targeted
    devices use the same value (use with --device <id> to be explicit).
    Nil falls back to per-device auto-allocation
    (Tunnel.dist_port(idx) + Discovery.Android.device_node_suffix /
    SIMULATOR_UDID-derived suffix). Resolves the
    register/listen error: no_reg_reply_from_epmd symptom seen when running
    multiple sims/emulators of the same app concurrently for cross-platform
    visual comparison.
  • MobDev.Device struct gains a :node_suffix field for plumbing the
    override per-device alongside :dist_port. Nil keeps auto-derive.
  • MobDev.Discovery.IOS.launch_app/3 accepts :node_suffix opt and
    forwards as SIMCTL_CHILD_MOB_NODE_SUFFIX to the launched sim. Companion
    to mob 0.6.10's MOB_NODE_SUFFIX support in mob_beam.m.
  • MobDev.Discovery.IOS.build_simctl_env/2 — pure helper extracted from
    launch_app/3 so override behaviour is unit-testable without spawning
    simctl. 7 new tests cover dist_port + node_suffix override paths.

Changed

  • MobDev.Connector.restart_app/1 pattern-matches :node_suffix from
    Device in both Android + iOS-sim variants, threading the value to the
    launchers.
  • MobDev.Deployer.deploy_all/1 accepts top-level :dist_port +
    :node_suffix opts; threaded through deploy_android and
    deploy_ios_simulator.

0.5.9

18 May 04:38

Choose a tag to compare

Changed

  • mix mob.enable tflite now injects {:nx_tflite_mob, "~> 0.0.3"}
    (Hex) instead of the GitHub-branch form. nx_tflite_mob v0.0.3 went
    live on Hex with 16 integration tests + a reproducible Mac host
    build path (see
    its CHANGELOG).
    Downstream Mob apps now get version-pinned deps + clean
    mix deps.tree output, instead of a transient github: checkout.

Notes

  • The Mac host-build path in nx_tflite_mob is for that package's own
    test suite, not for downstream consumers — production phone builds
    via mix mob.deploy --native continue to use the prebuilt Android
    AAR + iOS xcframework that mob_dev's MobDev.TfliteDownloader
    fetches.

0.5.8

17 May 23:07

Choose a tag to compare

Added

  • End-to-end mix mob.enable tflite — what 0.5.7 promised as
    "lands in 0.5.8". MobDev.NativeBuild now auto-detects the
    :nx_tflite_mob dep and threads the full TFLite path through
    Android + iOS sim + iOS device build pipelines:
    • maybe_build_tflite/1MobDev.TfliteDownloader.ensure/1 +
      MobDev.TfliteNif.build/2 for each target arch
    • tflite_zig_args_android/1 emits -Dtflite_static=true -Dtflite_lib=… for the per-ABI Android link
    • tflite_zig_args_ios/1 emits -Dtflite_static=true -Dtflite_dir=… -Dtflite_framework_dir=… for the iOS link
    • copy_tflite_runtime_lib_android/2 drops
      libtensorflowlite_jni.so into android/app/src/main/jniLibs/<abi>/
      during the assemble step
  • copy_tflite_frameworks_ios/3 (kept as future-compat hook) — see
    the iOS-deploy-fix gotcha below
  • 13 new tests covering the public NativeBuild plumbing
    (native_build_tflite_test.exs), bringing the TFLite suite to 76
    passing total

Fixed

  • iOS deploy: TFLite framework binaries are MH_OBJECT, not
    MH_DYLIB.
    TFLite's iOS xcframework slices ship their binaries as
    filetype=1 relocatable objects, which the linker statically pulls
    into the app's main Mach-O at build time. Trying to embed them as
    runtime .framework bundles tripped iOS install twice during this
    cut: first on missing per-framework Info.plist (which CocoaPods
    generates), then on "code signature version no longer supported"
    (iOS 26+ rejects v1 signatures, and codesign only makes v3 sigs
    for MH_EXECUTE/MH_DYLIB). The fix is to do nothing — the framework
    search-path arg already covers everything at build time.
  • Resolve :nx_tflite_mob via Mix.Project.deps_paths() rather
    than Path.join(deps_path, "nx_tflite_mob"). The latter assumes
    the dep landed in deps/ (hex / git deps do), but path: deps
    consume in-place from the user's source tree.

Verified on real hardware

  • Moto G Power 5G (BXM-8-256, Android 15): 75-117 ms YOLOv8n via
    NNAPI / mtk-gpu_shim
  • iPhone SE 3rd gen (A15, iOS 26.4): 24 ms YOLOv8n via Core ML → ANE
    (FP16 model; 214/385 nodes delegated)