diff --git a/CHANGELOG.md b/CHANGELOG.md index d2487213..ef90d7bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Fixed an include path issue on macOS when homebrew Python is installed: + if `sys.prefix` contains a symlink (as is the case with homebrew), resolve it + so that host include paths are still replaced by the cross-compile ones + [#375](https://github.com/pyodide/pyodide-build/pull/375) + ## [0.35.0] - 2026/06/09 ### Added diff --git a/pyodide_build/pywasmcross.py b/pyodide_build/pywasmcross.py index 80a6c24f..375937c2 100755 --- a/pyodide_build/pywasmcross.py +++ b/pyodide_build/pywasmcross.py @@ -161,14 +161,14 @@ def replay_genargs_handle_dashI(arg: str, target_install_dir: str) -> str | None if include_path_str.startswith("/usr"): return None - # Replace local Python include paths with the cross compiled ones + # Replace local Python include paths with the cross compiled ones. + # (resolve symlinks, since on macOS/homebrew Python sys.prefix will contain a symlink) include_path = str(Path(include_path_str).resolve()) - if include_path.startswith(sys.prefix + "/include/python"): - return arg.replace("-I" + sys.prefix, "-I" + target_install_dir) - - if include_path.startswith(sys.base_prefix + "/include/python"): - return arg.replace("-I" + sys.base_prefix, "-I" + target_install_dir) + for prefix in (sys.prefix, sys.base_prefix): + prefix = str(Path(prefix).resolve()) + if include_path.startswith(prefix + "/include/python"): + return "-I" + target_install_dir + include_path.removeprefix(prefix) return arg diff --git a/pyodide_build/tests/test_pywasmcross.py b/pyodide_build/tests/test_pywasmcross.py index 9292b15c..8f6f5928 100644 --- a/pyodide_build/tests/test_pywasmcross.py +++ b/pyodide_build/tests/test_pywasmcross.py @@ -147,6 +147,27 @@ def test_replay_genargs_handle_dashI(monkeypatch): ) +def test_replay_genargs_handle_dashI_symlinked_prefix(monkeypatch, tmp_path): + # sys.prefix may contain a symlink (e.g. homebrew Python on macOS: + # /opt/homebrew/opt/python@X.Y -> ../Cellar/...); the include path must be + # recognized nonetheless. + import sys + + real_prefix = tmp_path / "Cellar" / "python3.11" + (real_prefix / "include" / "python3.11").mkdir(parents=True) + link_prefix = tmp_path / "opt" / "python3.11" + link_prefix.parent.mkdir() + link_prefix.symlink_to(real_prefix) + + monkeypatch.setattr(sys, "prefix", str(link_prefix)) + monkeypatch.setattr(sys, "base_prefix", str(link_prefix)) + + assert ( + replay_genargs_handle_dashI(f"-I{link_prefix}/include/python3.11", "/target") + == "-I/target/include/python3.11" + ) + + def test_conda_unsupported_args(build_args): # Check that compile arguments that are not supported by emcc and are sometimes # used in conda are removed.