Building from source

mew is built with CMake using scikit-build-core, and the C++ extension uses nanobind.

Prerequisites

  • Python 3.11+

  • CMake ≥ 3.21

  • A C++17 compiler (Clang, GCC, MSVC).

  • uv — recommended for environments and locking.

  • prek — pre-commit runner used in CI.

One-time setup

$ uv sync --all-extras
$ uvx prek install

uv sync builds the C++ extension into the project’s .venv via scikit-build-core. The [tool.uv] config in pyproject.toml opts the project out of build isolation, so nanobind include paths incompile_commands.json survive wheel builds. This is useful for C++ language servers like clangd.

Rebuilding after a C++ change

$ uv sync --reinstall-package=mew  # editable install picks up the rebuilt .so

Alternatively, rebuild using CMake directly:

$ cmake --build build

Test, lint, type-check

$ uv run pytest tests/ -q
$ uvx prek run --all-files
$ uvx ty check src/mew/ tests/

These steps run in CI (.github/workflows/ci.yml) across Linux, macOS, and Windows on Python 3.11–3.14.

AddressSanitizer

Build a separate ASAN wheel (lands in build/asan/, leaving the Release wheel alone; a plain uv sync afterwards swaps the editable install back to Release):

$ MEW_ASAN=1 uv sync --all-groups --reinstall-package=mew

uv run pytest alone does not preload the ASAN runtime, so the test process aborts at the first import of an ASAN-built extension. Preload it explicitly:

# Linux: preload the ASAN runtime *and* libc++. libc++ must be preloaded too,
# otherwise its container-overflow annotations don't line up with the
# instrumented build and ASAN reports false positives.
MEW_ASAN=1 LD_PRELOAD="$(clang -print-file-name=libclang_rt.asan.so) $(clang -print-file-name=libc++.so)" \
    ASAN_OPTIONS="detect_leaks=0:halt_on_error=1" uv run --all-groups pytest --capture no

# for macOS, there's a wrapper script to work around SIP.
scripts/asan-pytest.sh

Building the documentation locally

$ uv pip install -e '.[docs]'
$ uv run sphinx-build -W --keep-going -b html docs docs/_build/html
$ open docs/_build/html/index.html

The -W flag mirrors readthedocs’ fail_on_warning: true switch.