Skip to content

fix(setup): patch python-olm bundled libolm for macOS Apple clang - #31354

Open
ayushere wants to merge 1 commit into
NousResearch:mainfrom
ayushere:fix/matrix-python-olm-macos-clang
Open

fix(setup): patch python-olm bundled libolm for macOS Apple clang#31354
ayushere wants to merge 1 commit into
NousResearch:mainfrom
ayushere:fix/matrix-python-olm-macos-clang

Conversation

@ayushere

Copy link
Copy Markdown
Contributor

Problem

On macOS with Apple clang (Xcode 15+), ensure("platform.matrix") always fails during the mautrix[encryption] install:

error: cannot assign to variable 'other_pos' with const-qualified type 'T *const'
  106 |             ++other_pos;
      |             ^ ~~~~~~~~~
make: *** [build/release/src/account.o] Error 1
× Getting requirements to build wheel did not run successfully.

mautrix[encryption] pulls in python-olm 3.2.16, which bundles its own libolm source. That source has a C++ bug in libolm/include/olm/list.hh — a local pointer variable is declared T * const other_pos then immediately incremented (++other_pos). Incrementing a const pointer is a hard compile error, not a warning, so -Wno-error cannot suppress it.

The same root cause was addressed for Docker in #27795 (apt-get install libolm-dev), but macOS users hit it every time Matrix E2EE lazy-install runs.

Fix

When ensure("platform.matrix") runs on darwin, pre-install python-olm from a patched copy of the PyPI sdist before the main pip install. The patch is a single-line removal of the spurious const qualifier:

- T * const other_pos = other._data;
+ T * other_pos = other._data;

Once python-olm is installed, mautrix[encryption]'s dep-resolution sees it satisfied and pip skips the bundled-source build entirely — no double build, no churn on subsequent runs.

The patch function is idempotent: if the target line is absent (upstream fixed the bug), it logs a warning and continues without patching.

Related

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • tools/lazy_deps.py — added _python_olm_macos_install() that downloads the sdist, patches list.hh, and installs via pip --no-build-isolation; hooked into ensure() for platform.matrix on darwin.

Test

# On a fresh macOS venv without python-olm:
python -c "from tools.lazy_deps import ensure; ensure('platform.matrix')"
# Should complete without error and import mautrix + olm cleanly
python -c "import mautrix; import olm; print('ok')"

Copilot AI review requested due to automatic review settings May 24, 2026 07:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a macOS-specific pre-install step to patch and build python-olm from sdist before installing mautrix[encryption], working around an Apple clang compile failure in the bundled libolm headers.

Changes:

  • Introduces _python_olm_macos_install() to download, patch, and install python-olm on macOS.
  • Hooks the pre-install into ensure("platform.matrix") and surfaces failures via FeatureUnavailable.
  • Adds logging around the patching/install process.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/lazy_deps.py
Comment on lines +386 to +387
with tarfile.open(tarball, "r:gz") as tf:
tf.extractall(tmpdir)
Comment thread tools/lazy_deps.py
Comment on lines +358 to +372
Returns ``None`` when this path is not needed (non-macOS, or python-olm
already installed). Returns an ``_InstallResult`` otherwise so callers
can surface failures.
"""
if sys.platform != "darwin":
return None
if _is_satisfied("python-olm"):
return None

import tarfile
import tempfile
import urllib.request

# Pin matches what mautrix[encryption]==0.21.0 resolves to.
OLM_VERSION = "3.2.16"
Comment thread tools/lazy_deps.py Outdated
Comment on lines +567 to +568
f"macOS pre-install of python-olm failed: {snippet or 'no output'}. "
"Try: brew install libolm, then re-run.",
Comment thread tools/lazy_deps.py
Comment on lines +402 to +413
patched = src.replace(
"T * const other_pos = other._data",
"T * other_pos = other._data",
)
if patched != src:
with open(list_hh, "w") as fh:
fh.write(patched)
logger.debug("macOS: patched libolm list.hh const-pointer bug")
else:
logger.warning(
"macOS: python-olm patch target not found in list.hh — "
"upstream may have fixed the bug; proceeding without patch"
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists platform/matrix Matrix adapter (E2EE) labels May 24, 2026
@ayushere
ayushere force-pushed the fix/matrix-python-olm-macos-clang branch from 5fcd3ba to 9424a64 Compare May 24, 2026 08:34
@ayushere

Copy link
Copy Markdown
Contributor Author

Re: test_model_switch_uses_requested_provider failure (CI run 3)

This test failure is pre-existing and unrelated to this PR. It fails on main as well — it appears to be a flaky test tied to LLM provider routing that our changes don't touch at all. The ruff, Windows footguns, and check-attribution CI checks all pass now.

Copilot comments addressed:

  • Version check tightened: _is_satisfied("python-olm==3.2.16") so a wrong-version install triggers a rebuild
  • Tarball path traversal guard added before extractall
  • Error message double-period fixed (trailing . removed from reason string; FeatureUnavailable._format() appends its own)
  • Misleading brew install libolm hint removed — brew libolm doesn't help since python-olm always builds its bundled copy

On macOS, `mautrix[encryption]` pulls in python-olm 3.2.16, which
bundles libolm source containing a C++ const-pointer bug in
`libolm/include/olm/list.hh`:

    T * const other_pos = other._data;
    // ...
    ++other_pos;   // error: cannot assign to const-qualified variable

Apple clang (Xcode 15+) rejects this as a hard compile error even
without -Werror, so `platform.matrix` lazy-install always fails on
macOS with:

    error: subprocess-exited-with-error
    × Getting requirements to build wheel did not run successfully.

Fix: when `ensure("platform.matrix")` runs on darwin, pre-install
python-olm from a patched copy of the sdist (one-line removal of the
spurious `const` qualifier) before the main pip install runs.
mautrix[encryption] then finds python-olm already satisfied and skips
the broken bundled-source build.

The patch is idempotent — if the target line is absent (upstream fixed
it), we log a warning and proceed without patching.

Relates to: NousResearch#27795 (adds libolm-dev for Docker, same root cause)
Relates to: NousResearch#14139 (replaces python-olm with fresholm long-term)

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for isolating the python-olm compiler failure and for adding extraction-path validation.

Problems

  • Current documentation intentionally directs macOS E2EE through Linux proxy mode (website/docs/user-guide/messaging/matrix.md:744-765). A native macOS path needs a maintainer decision and matching support/docs update before it can be adopted.
  • The new subprocess at tools/lazy_deps.py:428 bypasses current lazy-install behavior: durable-target routing and constraints (tools/lazy_deps.py:640-655) plus the credential-scrubbed installer environment (tools/lazy_deps.py:657-670). This can fail on immutable-image deployments and diverges from the established security boundary.
  • The PR changes no tests; existing Matrix lazy-dependency tests cover Windows only (tests/tools/test_lazy_deps.py:335-377). The linked #39816 also documents a CMake 4 failure that this separate subprocess would not inherit from a helper-level fix.

Suggested changes

  • Confirm the native-macOS support direction, then route any patched-source build through the shared installer and add hermetic darwin regression coverage.

Automated hermes-sweeper review.

Comment thread tools/lazy_deps.py

src_dir = os.path.join(tmpdir, f"python-olm-{OLM_VERSION}")
pip_cmd = [sys.executable, "-m", "pip"]
r = subprocess.run(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bypasses the lazy installer’s current durable-target/constraint path and its credential-scrubbed subprocess environment (tools/lazy_deps.py:640-670 on main). Please route the patched-source build through the shared install mechanism (or extend it with a source-build input) so immutable deployments and the established subprocess boundary continue to work.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Medium — degraded but workaround exists platform/matrix Matrix adapter (E2EE) sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants