# `DalaDev.NativeBuild`
[🔗](https://github.com/manhvu/dala_dev/blob/main/lib/mob_dev/native_build.ex#L1)

Builds native binaries (APK for Android, .app bundle for iOS simulator)
for the current Dala project.

Reads paths from `dala.exs` in the project root. If `dala.exs` is missing
or paths haven't been configured, prints instructions and exits.

OTP runtimes for Android and iOS are downloaded automatically from GitHub
and cached at `~/.dala/cache/` by `DalaDev.OtpDownloader`.

## dala.exs keys

  * `:dala_dir`           — dala library repo (native C/ObjC/Swift source)
  * `:elixir_lib`        — Elixir stdlib lib dir

# `android_toolchain_available?`

```elixir
@spec android_toolchain_available?(String.t()) :: boolean()
```

Returns true when the Android build toolchain looks usable from the given
project directory. Three signals must all be present:

  1. `adb` is on PATH (build needs it to install the APK after Gradle)
  2. `<project_dir>/android/local.properties` exists and sets `sdk.dir`
  3. The directory `sdk.dir` points at exists on disk

Returns false otherwise so the deploy can skip Android cleanly instead of
failing late inside Gradle. Pure of side effects.

# `build_all`

```elixir
@spec build_all(keyword()) :: [:ok | {:error, term()}]
```

Builds native binaries for all platforms present in the project.
Runs Android Gradle build if `android/` dir exists.
Runs iOS build script if `ios/build.sh` exists (simulator), or
`xcodebuild` if targeting a physical iOS device via `device:` opt.

# `detect_physical_ios`

```elixir
@spec detect_physical_ios() :: String.t() | nil
```

Returns the UDID of the sole connected physical iOS device, or nil.
When exactly one physical device is connected, it can be used automatically.
With zero or 2+ physical devices, returns nil.

# `ios_toolchain_available?`

```elixir
@spec ios_toolchain_available?() :: boolean()
```

Returns true when an iOS build is feasible: macOS host with `xcrun`
installed. Linux/Windows always returns false. Pure of side effects.

# `narrow_platforms_for_device`

```elixir
@spec narrow_platforms_for_device([atom()], String.t() | nil) :: [atom()]
```

When `--device <id>` is given, narrow `platforms` to just the platform
the device lives on. Drops Android when the id resolves to an iOS
device (sim or physical), drops iOS otherwise.

Public so `mix dala.deploy` can apply the same narrowing before calling
`DalaDev.Deployer.deploy_all/1` — otherwise the deployer's per-platform
`filter_by_device_id` complains "No device matched" against the
irrelevant platform even though the build itself was correctly
targeted.

Returns `platforms` unchanged when `device_id` is nil.

# `narrow_platforms_for_device`

```elixir
@spec narrow_platforms_for_device([atom()], String.t() | nil, (-&gt; [DalaDev.Device.t()])) ::
  [atom()]
```

Variant that takes an iOS-discovery function so tests (and other
callers that already have the device list in hand) can avoid the
network-bound `IOS.list_devices/0` LAN scan.

The lister is called at most once per invocation; both `ios_device?`
and the physical-UDID format fallback consume the same result.

# `otp_dir_for_abi`

```elixir
@spec otp_dir_for_abi(String.t(), String.t(), String.t()) :: String.t()
```

Returns the OTP directory for the given Android ABI string.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
