Builds the assets/otp.zip that release-mode Android Mob apps extract on
first launch.
Mirrors the elixir-desktop example-app pattern (their Bridge.kt:unpackZip())
but with Mob-specific stripping inherited from the iOS release pass — drops
unused OTP libs and standalone executables to shave bundle size and avoid
shipping anything Mob never actually executes.
Called from mix mob.release --android (Workstream 3). Kept as a separate
module so the strip rules + zip layout are testable without spinning up
the full release pipeline.
Layout produced
otp.zip
├── erts-VSN/... (BEAM emulator support — minus bin/)
├── lib/elixir-VSN/...
├── lib/logger-VSN/...
├── lib/eex-VSN/...
├── lib/<other-otp-libs-the-app-uses>/...
└── releases/...The MobBridge.extractOtpIfNeeded() Kotlin function unzips this into
<filesDir>/otp/ on first launch, keyed by PackageInfo.lastUpdateTime
so app updates trigger a re-extract.
What gets stripped
Three categories, mirroring the iOS strip pass in MobDev.Release:
- Whole OTP libs the framework doesn't use —
megaco,runtime_tools,wx,observer,debugger, etc. These are dead weight in a Mob app. - Standalone executables —
priv/bin/*anderts-*/bin/*. The few that Mob actually executes (erl_child_setup,inet_gethost,epmd) are packaged separately injniLibs/<abi>/aslib<name>.soso they get theapk_data_fileSELinux label that allows execve from untrusted_app. The rest aren't reachable. - Static archives (
.a) — already linked into the app's native lib at build time. Shipping them inside the runtime tree is pure waste.
.so files inside OTP libs (e.g. priv/lib/asn1.so) are KEPT in the zip —
they're loaded by the BEAM at runtime via dlopen(), which works fine from
app data dir on Android (only execve() is blocked).
Summary
Functions
Builds the OTP asset zip from source_otp_tree into target_zip_path.
Returns the list of OTP lib name prefixes that are stripped by default. Public so tests can assert the policy without re-importing the module-private list.
Functions
Builds the OTP asset zip from source_otp_tree into target_zip_path.
Returns {:ok, %{zipped_files: count, original_size_kb: integer, zip_size_kb: integer}} on success, {:error, reason} on failure.
Options
:strip_extra_prefixes— additional OTP lib prefixes to drop on top of the default list. Atoms or strings.:keep_prefixes— prefixes to KEEP even if in the default strip list. Lets a specific app opt back into a stripped lib.
@spec default_stripped_prefixes() :: [String.t()]
Returns the list of OTP lib name prefixes that are stripped by default. Public so tests can assert the policy without re-importing the module-private list.