<!-- Source: https://medius.k4tech.net/bindings/python/build -->
# Build & features

_Turning on mock and flash, and building from source_

The [mock](/library/features/mock.md) and [flash](/library/features/flash.md) features are compiled into the native library, not switched on from Python, so turning one on means building that library. The `[pip](https://pip.pypa.io) install medius` wheel ships with both off. Everything else is a [ctypes](https://docs.python.org/3/library/ctypes.html) layer with no Python build step.

## Feature flags

_mock and flash, and how to tell what's built in_

Both are [Cargo features](https://doc.rust-lang.org/cargo/reference/features.html) on the [`medius-capi`](https://github.com/K4HVH/medius) crate. On import, Python reads what the loaded library exposes and sets `medius.HAS_MOCK` and `medius.HAS_FLASH` to match.

| Feature | Cargo flag | Python surface | `medius.HAS_*` | Adds |
| --- | --- | --- | --- | --- |
| `mock` | `--features mock` | `MockBox().open()` / `.with_device()` | `HAS_MOCK` | A scriptable in-process fake box. See [Mock box](/library/features/mock.md). |
| `flash` | `--features flash` | [`medius.flash(port, bin_path, host=False)`](/bindings/python/api.md#module) | `HAS_FLASH` | Flash firmware via [esptool](https://github.com/espressif/esptool), Linux and Windows. See [Flash](/library/features/flash.md). |

> **Warning**
>
> The `pip install medius` wheel has neither feature. `MockBox()` and `medius.flash(...)` raise `[RuntimeError](https://docs.python.org/3/library/exceptions.html#RuntimeError)` there. Gate on the flag first: `if medius.HAS_MOCK:` / `if medius.HAS_FLASH:`.

#### CHECK WHAT'S BUILT IN

```bash
python -c "import medius; print('mock', medius.HAS_MOCK, 'flash', medius.HAS_FLASH)"
# mock False flash False   <- the published wheel
```

#### ENABLE A FEATURE

Build the library with the features you want, then point Python at it with `MEDIUS_LIB` ([below](/bindings/python/build.md#loading)). No reinstall.

```bash
# from the repo root
cargo build --release -p medius-capi --features mock,flash

export MEDIUS_LIB=$PWD/target/release/libmedius_capi.so
python -c "import medius; print(medius.HAS_MOCK, medius.HAS_FLASH)"
# True True
```

To bake features into an installed wheel, build the library first and let pip reuse it:

```bash
cargo build --release -p medius-capi --features mock,flash
MEDIUS_SKIP_CARGO=1 pip install ./bindings/python
```

## Finding the library

_MEDIUS_LIB and the load order_

On `import medius` the package loads the native library, trying these in order and stopping at the first hit. Set `MEDIUS_LIB` to override the rest and run any script against the build you want (a debug build, or one with [mock](/library/features/mock.md)/[flash](/library/features/flash.md)).

```
import medius
   │
   ├─ 1. $MEDIUS_LIB set?                   ──▶  CDLL(that exact path)   (dev / test builds)
   ├─ 2. bundled beside the package?        ──▶  CDLL(medius/<libname>)  (what the wheel ships)
   ├─ 3. on the system loader path?         ──▶  CDLL(<libname>)         (LD_LIBRARY_PATH / PATH)
   ├─ 4. ctypes.util.find_library(...)?     ──▶  CDLL(found)             (ldconfig / system paths)
   └─ none                                  ──▶  OSError                 (cannot locate the library)
```

#### POINT AT ANY BUILD WITH MEDIUS_LIB

```python
MEDIUS_LIB=/path/to/target/release/libmedius_capi.so python myscript.py
```

> **Warning**
>
> An `[OSError](https://docs.python.org/3/library/exceptions.html#OSError)` on import means every step failed: a bad `MEDIUS_LIB` path, or an unsupported platform where the install built from source without a [Rust toolchain](https://rustup.rs).

## Build from source

_musl Linux, 32-bit Windows, and contributors_

Linux ([glibc](https://www.gnu.org/software/libc/)), macOS, and 64-bit Windows get a prebuilt wheel from `pip install medius`. On [musl](https://musl.libc.org) Linux ([Alpine](https://alpinelinux.org)) or 32-bit Windows there's no wheel, so `pip` builds the native library from source. Force a source build anywhere, or build from a checkout:

```bash
# build from source even where a wheel exists
pip install medius --no-binary medius

# from a checkout
pip install ./bindings/python
```

> **Warning**
>
> A source build runs `cargo build --release -p medius-capi`, so it needs a [Rust toolchain](https://rustup.rs) on PATH. On Linux the library links `[libudev](https://www.freedesktop.org/software/systemd/man/latest/libudev.html)` through [serialport](https://crates.io/crates/serialport); install `systemd-devel` (or your distro's `libudev-dev`) first.
