From fac0109aa2acf14469320b049d710dd42639bf94 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Wed, 17 Jul 2024 22:20:30 +0900 Subject: [PATCH] Allow overriding _f2c_fixes.py from user (#8) While most parts of pyodide-build are decoupled with pyodide/pyodide, `_f2c_fixes.py` file that is used to build scipy is highly coupled with the scipy recipe in pyodide/pyodide. It would be very inefficient if we need to update pyodide-build whenever we fix scipy (e.g. https://github.com/pyodide/pyodide/issues/4818). Therefore, this add a private config variable `_f2c_fixes_wrapper`, which allows users to modify override `_f2c_fixes.py` file without touching pyodide-build itself. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 5 +++++ pyodide_build/config.py | 6 ++++++ pyodide_build/pypabuild.py | 16 +++++++++++++--- pyodide_build/pywasmcross.py | 4 ++-- pyodide_build/tests/test_pypabuild.py | 20 +++++++++++++++++++- 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 032ac92..43f3b2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.27.3] - 2024/07/17 + +- It is now possible to override `_f2c_fixes.py` file, with `_f2c_fixes_wrapper` variable. + [#8](https://github.com/pyodide/pyodide-build/pull/8) + ## [0.27.2] - 2024/07/11 ## Changed diff --git a/pyodide_build/config.py b/pyodide_build/config.py index e0661b9..b4b7176 100644 --- a/pyodide_build/config.py +++ b/pyodide_build/config.py @@ -169,6 +169,8 @@ def to_env(self) -> dict[str, str]: "home": "HOME", "path": "PATH", "zip_compression_level": "PYODIDE_ZIP_COMPRESSION_LEVEL", + # maintainer only + "_f2c_fixes_wrapper": "_F2C_FIXES_WRAPPER", } BUILD_VAR_TO_KEY = {v: k for k, v in BUILD_KEY_TO_VAR.items()} @@ -181,6 +183,8 @@ def to_env(self) -> dict[str, str]: "ldflags", "rust_toolchain", "meson_cross_file", + # maintainer only + "_f2c_fixes_wrapper", } # Default configuration values. @@ -197,6 +201,8 @@ def to_env(self) -> dict[str, str]: "rust_toolchain": "nightly-2024-01-29", # Other configuration "pyodide_jobs": "1", + # maintainer only + "_f2c_fixes_wrapper": "", } # Default configs that are computed from other values (often from Makefile.envs) diff --git a/pyodide_build/pypabuild.py b/pyodide_build/pypabuild.py index bd03f23..f6e5aff 100644 --- a/pyodide_build/pypabuild.py +++ b/pyodide_build/pypabuild.py @@ -15,7 +15,7 @@ from build.env import DefaultIsolatedEnv from packaging.requirements import Requirement -from . import common, pywasmcross +from . import _f2c_fixes, common, pywasmcross from .build_env import ( get_build_flag, get_hostsitepackages, @@ -214,10 +214,20 @@ def make_command_wrapper_symlinks(symlink_dir: Path) -> dict[str, str]: The dictionary of compiler environment variables that points to the symlinks. """ + # For maintainers: + # - you can set "_f2c_fixes_wrapper" variable in pyproject.toml + # in order to change the script to use when cross-compiling + # this is only for maintainers and *should* not be used by others + pywasmcross_exe = symlink_dir / "pywasmcross.py" - shutil.copy2(pywasmcross.__file__, pywasmcross_exe) + pywasmcross_origin = pywasmcross.__file__ + shutil.copy2(pywasmcross_origin, pywasmcross_exe) pywasmcross_exe.chmod(0o755) + f2c_fixes_exe = symlink_dir / "_f2c_fixes.py" + f2c_fixes_origin = get_build_flag("_F2C_FIXES_WRAPPER") or _f2c_fixes.__file__ + shutil.copy2(f2c_fixes_origin, f2c_fixes_exe) + env = {} for symlink in pywasmcross.SYMLINKS: symlink_path = symlink_dir / symlink @@ -266,7 +276,7 @@ def get_build_env( env.update(make_command_wrapper_symlinks(symlink_dir)) sysconfig_dir = Path(get_build_flag("TARGETINSTALLDIR")) / "sysconfigdata" - args["PYTHONPATH"] = sys.path + [str(sysconfig_dir)] + args["PYTHONPATH"] = sys.path + [str(symlink_dir), str(sysconfig_dir)] args["orig__name__"] = __name__ args["pythoninclude"] = get_build_flag("PYTHONINCLUDE") args["PATH"] = env["PATH"] diff --git a/pyodide_build/pywasmcross.py b/pyodide_build/pywasmcross.py index 6d8a1a3..858b748 100755 --- a/pyodide_build/pywasmcross.py +++ b/pyodide_build/pywasmcross.py @@ -591,7 +591,7 @@ def handle_command( """ if line[0] == "gfortran": - from pyodide_build._f2c_fixes import replay_f2c + from _f2c_fixes import replay_f2c tmp = replay_f2c(line) if tmp is None: @@ -604,7 +604,7 @@ def handle_command( new_args = handle_command_generate_args(line, build_args) if build_args.pkgname == "scipy": - from pyodide_build._f2c_fixes import scipy_fixes + from _f2c_fixes import scipy_fixes scipy_fixes(new_args) diff --git a/pyodide_build/tests/test_pypabuild.py b/pyodide_build/tests/test_pypabuild.py index 68dbf29..7a0af3f 100644 --- a/pyodide_build/tests/test_pypabuild.py +++ b/pyodide_build/tests/test_pypabuild.py @@ -50,7 +50,25 @@ def test_make_command_wrapper_symlinks(tmp_path): assert key in pypabuild.SYMLINK_ENV_VARS.values() -def test_get_build_env(tmp_path): +def test_make_command_wrapper_symlinks_f2c_wrapper( + tmp_path, dummy_xbuildenv, reset_env_vars, reset_cache +): + import os + + dummy_f2c_wrapper = tmp_path / "_dummy_f2c_fixes.py" + dummy_f2c_wrapper.write_text("print('Hello, world!')") + + os.environ["_F2C_FIXES_WRAPPER"] = str(dummy_f2c_wrapper) + + symlink_dir = tmp_path + pypabuild.make_command_wrapper_symlinks(symlink_dir) + + wrapper = symlink_dir / "_f2c_fixes.py" + assert wrapper.exists() + assert wrapper.read_text() == dummy_f2c_wrapper.read_text() + + +def test_get_build_env(tmp_path, dummy_xbuildenv): build_env_ctx = pypabuild.get_build_env( env={"PATH": ""}, pkgname="",