Reachability analysis for the bundled OTP runtime tree of a Mob app.
Walks every .beam file under an OTP root, extracts the imports chunk
to learn who calls whom, and computes the transitive closure starting
from the app's entry-point modules. Anything not reachable is a strip
candidate — modules, whole libs, or duplicate library versions.
Used by mix mob.audit_otp (read-only report) and the planned
mix mob.release --slim flag (auto-strip based on the report).
Entry points
Reachability seeding is deliberately generous:
- App's
start/2callback module (read from each.appfile'smodkey) - All exported functions of
kernelandstdlib(BEAM startup needs them) elixir,logger,eex(runtime support that gets called via macros)
Anything reachable from those is kept; the rest is candidate-for-strip.
Output
Returns a map with:
:libs— every lib found, with reachable/total module counts and KB:duplicates— libs that appear multiple times (only newest is kept):foreign_apps— non-OTP, non-app code in the lib dir (other projects):strippable_libs— libs with zero reachable modules:total_kb/:reachable_kb/:strippable_kb— size summary
All sizes are post-strip — i.e. what mix mob.release actually ships,
not raw OTP source.
Summary
Functions
Run the audit. otp_root is the directory containing lib/ and erts-*/
(typically the runtime tree extracted into the app bundle, or the cache
the release packaging copies from).
Types
@type lib_name() :: String.t()
@type lib_report() :: %{ name: lib_name(), version: String.t() | nil, path: String.t(), modules_total: non_neg_integer(), modules_reachable: non_neg_integer(), kb_total: non_neg_integer(), kb_reachable: non_neg_integer(), unreachable_modules: [module_atom()], is_app_under_test?: boolean() }
@type module_atom() :: atom()
@type report() :: %{ otp_root: String.t(), app_name: String.t() | nil, libs: [lib_report()], duplicates: %{required(lib_name()) => [String.t()]}, foreign_apps: [String.t()], strippable_libs: [lib_name()], total_kb: non_neg_integer(), reachable_kb: non_neg_integer(), strippable_kb: non_neg_integer() }
Functions
Run the audit. otp_root is the directory containing lib/ and erts-*/
(typically the runtime tree extracted into the app bundle, or the cache
the release packaging copies from).
:app_name (option) — the application's atom name (e.g. :air_cart_max).
Used to seed reachability from the app's modules. If omitted, every lib
with no mod callback is treated as a potential entry point (broader,
finds less to strip).