mix mob.deploy (mob_dev v0.5.5)

Copy Markdown View Source

Compiles the project then pushes BEAM files to all connected Android devices and iOS simulators.

Modes

Fast deploy (default) — push BEAMs + restart. Use this for day-to-day Elixir code changes. Requires the native app already installed on device.

mix mob.deploy

Full deploy — build native binary + install APK/app + push BEAMs. Use this the first time, or after changes to native C/Java/Swift code.

mix mob.deploy --native

Options

  • --native — build native binaries before pushing BEAMs

  • --no-restart — push BEAMs but don't restart the app

  • --device <id> — target a specific device; use mix mob.devices to find IDs

  • --schedulers <N> — set BEAM scheduler count (saved to mob.exs)

  • --beam-flags "<flags>" — arbitrary BEAM flags string (saved to mob.exs)

  • --slim — strip OTP source/debug for size measurement on

                          a real device. OFF by default for dev iteration
                          (the strip pass adds ~5-10s per build); use this
                          to verify a slim build runs before
                          `mix mob.republish` round-trips through TestFlight.
                          The strip set is controlled by `MobDev.OtpAudit.Slim`;
                          per-app overrides live in `mob.exs`:
    
                              config :mob_dev,
                                slim: [
                                  drop_libs: ["my_unused_dep"],
                                  keep_libs: ["mnesia"],
                                  audit: true,                       # opt in
                                  # Single capture (a starting point):
                                  trace_json: "priv/mob_trace.json",
                                  # OR multiple captures unioned —
                                  # much safer for production
                                  # stripping. A lib is trace-
                                  # strippable only if NONE of the
                                  # captures observed any of its
                                  # modules.
                                  trace_jsons: [
                                    "priv/boot.json",
                                    "priv/ui.json",
                                    "priv/auth.json"
                                  ]
                                ]
    
                          With `audit: true`, the slim pass runs
                          `MobDev.OtpAudit` against the bundle and
                          expands the strip set with foreign apps
                          + (when a trace is supplied) the
                          trace-augmented strip set. Trace JSON
                          comes from `mix mob.trace_otp --json`.

BEAM scheduler tuning

The default native build uses 1:1 (single scheduler) for battery efficiency. Override for the current deploy and all future deploys until changed:

# Pin to 2 schedulers
mix mob.deploy --schedulers 2

# Let BEAM auto-detect — one scheduler per logical core
mix mob.deploy --schedulers 0

# Arbitrary flags (replaces --schedulers)
mix mob.deploy --beam-flags "-S 4:4 -A 4"

The chosen value is written to mob.exs under beam_flags: and reused on subsequent mix mob.deploy runs that don't pass either flag. The flags are written alongside the BEAMs as a mob_beam_flags file that the native launcher reads at startup — no APK/app rebuild required.

Under the hood

A fast deploy is equivalent to:

mix deps.get                                     # only with --native
mix compile

# Android
adb push _build/prod/lib/*/ebin/*.beam /data/data/<pkg>/files/lib/*/ebin/
adb shell am force-stop <package>               # restart

# iOS simulator
xcrun simctl spawn <udid> cp <beam_files> <app_bundle>/

When Erlang distribution is already reachable (app running, node connected), mix mob.deploy skips adb push and hot-pushes via RPC instead — equivalent to calling nl(Module) in IEx for every changed module:

:rpc.call(node, :code, :load_binary, [Module, path, beam_binary])

With --native, it also runs the platform build before pushing BEAMs:

# Android
./gradlew assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

# iOS simulator
xcodebuild -scheme <app> -destination 'platform=iOS Simulator,...' build
xcrun simctl install booted <app>.app

Summary

Functions

Build the per-deploy summary lines from the three device buckets.

Functions

format_summary(deployed, failed, skipped, opts \\ [])

@spec format_summary([Device.t()], [Device.t()], [Device.t()], keyword()) :: [
  String.t()
]

Build the per-deploy summary lines from the three device buckets.

Returns an iolist of strings (one per line) that the task prints verbatim. Public so the report shape can be pinned against fixture device lists — keeps "Failed on N" from regressing back into counting skipped-because-not-installed devices.

Opts:

  • :restart — boolean; controls the post-deploy IEx hint line