diff --git a/docs/development/meta-yaml.md b/docs/development/meta-yaml.md index 0f5cf1c39..a0ab26b8f 100644 --- a/docs/development/meta-yaml.md +++ b/docs/development/meta-yaml.md @@ -103,6 +103,10 @@ Extra arguments to pass to the linker when building for WebAssembly. (This key is not in the Conda spec). +### `build/backend-flags` + +Extra flags to pass to the build backend (e.g., `setuptools`, `flit`, etc). + ### `build/library` Should be set to true for library packages. Library packages are packages that are needed for other packages but are not Python packages themselves. For library packages, the script specified in the `build/script` section is run to compile the library. See the [zlib meta.yaml](https://github.com/pyodide/pyodide/blob/main/packages/zlib/meta.yaml) for an example of a library package specification. diff --git a/packages/numpy/meta.yaml b/packages/numpy/meta.yaml index 6591091ba..c37719613 100644 --- a/packages/numpy/meta.yaml +++ b/packages/numpy/meta.yaml @@ -10,12 +10,12 @@ source: - patches/0001-make-int-return-values.patch - patches/0002-MAINT-BLD-Fix-math-feature-detection-for-wasm.patch - patches/0003-BUG-Fix-the-return-type-of-random_float_fill.patch - - patches/0004-disable-optimization.patch - patches/0005-Fix-ieee754.patch - patches/0006-not-build-lapack-lite-as-64-bit.patch - patches/0001-ENH-cross-compilation-use-sysconfig-to-determine-if-.patch build: + backend-flags: --disable-optimization cflags: | -Wno-return-type cross-build-env: true diff --git a/packages/numpy/patches/0004-disable-optimization.patch b/packages/numpy/patches/0004-disable-optimization.patch deleted file mode 100644 index f04ff2050..000000000 --- a/packages/numpy/patches/0004-disable-optimization.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 97b588ab3e321cc0fe6b226f6b2eb3c5ae05bc09 Mon Sep 17 00:00:00 2001 -From: Hood Chatham -Date: Thu, 31 Mar 2022 17:17:30 -0700 -Subject: [PATCH 4/7] disable optimization - -This is to disable SIMD optimization until SAFARI has good support for it. ---- - numpy/distutils/command/build.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/numpy/distutils/command/build.py b/numpy/distutils/command/build.py -index a4fda537d..11fffe282 100644 ---- a/numpy/distutils/command/build.py -+++ b/numpy/distutils/command/build.py -@@ -37,7 +37,7 @@ def initialize_options(self): - self.warn_error = False - self.cpu_baseline = "min" - self.cpu_dispatch = "max -xop -fma4" # drop AMD legacy features by default -- self.disable_optimization = False -+ self.disable_optimization = True - """ - the '_simd' module is a very large. Adding more dispatched features - will increase binary size and compile time. By default we minimize --- -2.25.1 - diff --git a/pyodide-build/pyodide_build/buildpkg.py b/pyodide-build/pyodide_build/buildpkg.py index 20f496db0..364bb4602 100755 --- a/pyodide-build/pyodide_build/buildpkg.py +++ b/pyodide-build/pyodide_build/buildpkg.py @@ -444,6 +444,7 @@ def compile( pywasmcross.compile( env=bash_runner.env, pkgname=name, + backend_flags=build_metadata["backend-flags"], cflags=build_metadata["cflags"], cxxflags=build_metadata["cxxflags"], ldflags=build_metadata["ldflags"], @@ -878,6 +879,7 @@ def main(args): pkg["source"] = pkg.get("source", {}) pkg["build"] = pkg.get("build", {}) build_metadata = pkg["build"] + build_metadata["backend-flags"] = build_metadata.get("backend-flags", "") build_metadata["cflags"] = build_metadata.get("cflags", "") build_metadata["cxxflags"] = build_metadata.get("cxxflags", "") build_metadata["ldflags"] = build_metadata.get("ldflags", "") diff --git a/pyodide-build/pyodide_build/io.py b/pyodide-build/pyodide_build/io.py index a8a4036e0..60dba7d5b 100644 --- a/pyodide-build/pyodide_build/io.py +++ b/pyodide-build/pyodide_build/io.py @@ -19,6 +19,7 @@ PACKAGE_CONFIG_SPEC: dict[str, dict[str, Any]] = { "extras": list, # List[Tuple[str, str]], }, "build": { + "backend-flags": str, "cflags": str, "cxxflags": str, "ldflags": str, diff --git a/pyodide-build/pyodide_build/pypabuild.py b/pyodide-build/pyodide_build/pypabuild.py index 8572d56fc..fb31a3ad3 100644 --- a/pyodide-build/pyodide_build/pypabuild.py +++ b/pyodide-build/pyodide_build/pypabuild.py @@ -7,7 +7,7 @@ from itertools import chain from pathlib import Path from typing import Generator, Mapping -from build import BuildBackendException, ProjectBuilder +from build import BuildBackendException, ConfigSettingsType, ProjectBuilder from build.__main__ import ( _STYLES, _error, @@ -74,6 +74,7 @@ def _build_in_isolated_env( builder: ProjectBuilder, outdir: str, distribution: str, + config_settings: ConfigSettingsType, ) -> str: # For debugging: The following line disables removal of the isolated venv. # It will be left in the /tmp folder and can be inspected or entered as @@ -87,7 +88,7 @@ def _build_in_isolated_env( install_reqs(env, builder.build_system_requires) installed_requires_for_build = False try: - build_reqs = builder.get_requires_for_build(distribution) + build_reqs = builder.get_requires_for_build(distribution, config_settings) except BuildBackendException: pass else: @@ -96,19 +97,38 @@ def _build_in_isolated_env( with replace_env(build_env): if not installed_requires_for_build: - install_reqs(env, builder.get_requires_for_build(distribution)) - return builder.build(distribution, outdir, {}) + install_reqs( + env, builder.get_requires_for_build(distribution, config_settings) + ) + return builder.build(distribution, outdir, config_settings) -def build(build_env: Mapping[str, str]) -> None: +def parse_backend_flags(backend_flags: str) -> ConfigSettingsType: + config_settings: dict[str, str | list[str]] = {} + for arg in backend_flags.split(): + setting, _, value = arg.partition("=") + if setting not in config_settings: + config_settings[setting] = value + continue + + cur_value = config_settings[setting] + if isinstance(cur_value, str): + config_settings[setting] = [cur_value, value] + else: + cur_value.append(value) + return config_settings + + +def build(build_env: Mapping[str, str], backend_flags: str) -> None: srcdir = Path.cwd() outdir = srcdir / "dist" builder = _ProjectBuilder(str(srcdir)) distribution = "wheel" + config_settings = parse_backend_flags(backend_flags) try: with _handle_build_error(): built = _build_in_isolated_env( - build_env, builder, str(outdir), distribution + build_env, builder, str(outdir), distribution, config_settings ) print("{bold}{green}Successfully built {}{reset}".format(built, **_STYLES)) except Exception as e: # pragma: no cover diff --git a/pyodide-build/pyodide_build/pywasmcross.py b/pyodide-build/pyodide_build/pywasmcross.py index e1e94a005..3d0800ff4 100755 --- a/pyodide-build/pyodide_build/pywasmcross.py +++ b/pyodide-build/pyodide_build/pywasmcross.py @@ -80,6 +80,7 @@ def compile( env: dict[str, str], *, pkgname: str, + backend_flags: str, cflags: str, cxxflags: str, ldflags: str, @@ -88,6 +89,7 @@ def compile( ) -> None: kwargs = dict( pkgname=pkgname, + backend_flags=backend_flags, cflags=cflags, cxxflags=cxxflags, ldflags=ldflags, @@ -96,6 +98,7 @@ def compile( ) args = environment_substitute_args(kwargs, env) + backend_flags = args.pop("backend_flags") args["builddir"] = str(Path(".").absolute()) env = dict(env) @@ -109,10 +112,10 @@ def compile( env["_PYTHON_HOST_PLATFORM"] = common.platform() env["_PYTHON_SYSCONFIGDATA_NAME"] = os.environ["SYSCONFIG_NAME"] - from pyodide_build.pypabuild import build + from .pypabuild import build try: - build(env) + build(env, backend_flags) except BaseException: build_log_path = Path("build.log") if build_log_path.exists():