fix: don't error when a global build-frontend is set on pyodide (#2945)
Since #2609, the pyodide platform required the 'pyodide-build' frontend, but a global build-frontend setting (TOML or CIBW_BUILD_FRONTEND) overrides the platform default, so previously-working configs like build-frontend = "build" failed with a ConfigurationError. Even "default" failed, since it was mapped to "build" before the check. Resolve "default" to the platform default, and warn and use pyodide-build when another frontend is set on pyodide, matching pre-#2609 behavior where the frontend name only affected verbosity flags. Assisted-by: ClaudeCode:claude-opus-4.8
This commit is contained in:
+12
-4
@@ -43,7 +43,7 @@ from packaging.specifiers import SpecifierSet
|
|||||||
from cibuildwheel import errors
|
from cibuildwheel import errors
|
||||||
from cibuildwheel.architecture import Architecture
|
from cibuildwheel.architecture import Architecture
|
||||||
from cibuildwheel.environment import EnvironmentParseError, ParsedEnvironment, parse_environment
|
from cibuildwheel.environment import EnvironmentParseError, ParsedEnvironment, parse_environment
|
||||||
from cibuildwheel.frontend import BuildFrontendConfig
|
from cibuildwheel.frontend import BuildFrontendConfig, BuildFrontendName
|
||||||
from cibuildwheel.logger import log
|
from cibuildwheel.logger import log
|
||||||
from cibuildwheel.oci_container import OCIContainerEngineConfig
|
from cibuildwheel.oci_container import OCIContainerEngineConfig
|
||||||
from cibuildwheel.projectfiles import get_requires_python_str, resolve_dependency_groups
|
from cibuildwheel.projectfiles import get_requires_python_str, resolve_dependency_groups
|
||||||
@@ -850,8 +850,11 @@ class Options:
|
|||||||
env_plat=False,
|
env_plat=False,
|
||||||
option_format=ShlexTableFormat(sep="; ", pair_sep=":", allow_merge=False),
|
option_format=ShlexTableFormat(sep="; ", pair_sep=":", allow_merge=False),
|
||||||
)
|
)
|
||||||
|
default_frontend: BuildFrontendName = (
|
||||||
|
"pyodide-build" if self.platform == "pyodide" else "build"
|
||||||
|
)
|
||||||
if not build_frontend_str or build_frontend_str == "default":
|
if not build_frontend_str or build_frontend_str == "default":
|
||||||
build_frontend = BuildFrontendConfig("build")
|
build_frontend = BuildFrontendConfig(default_frontend)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
build_frontend = BuildFrontendConfig.from_config_string(build_frontend_str)
|
build_frontend = BuildFrontendConfig.from_config_string(build_frontend_str)
|
||||||
@@ -860,8 +863,13 @@ class Options:
|
|||||||
raise errors.ConfigurationError(msg) from e
|
raise errors.ConfigurationError(msg) from e
|
||||||
|
|
||||||
if self.platform == "pyodide" and build_frontend.name != "pyodide-build":
|
if self.platform == "pyodide" and build_frontend.name != "pyodide-build":
|
||||||
msg = "The pyodide platform requires the 'pyodide-build' build frontend"
|
# pip and uv could become an error, eventually. build -> pyodide-build is
|
||||||
raise errors.ConfigurationError(msg)
|
# probably fine to keep as a warning
|
||||||
|
log.warning(
|
||||||
|
f"The pyodide platform ignores the {build_frontend.name!r} build "
|
||||||
|
"frontend; using 'pyodide-build' instead"
|
||||||
|
)
|
||||||
|
build_frontend = BuildFrontendConfig("pyodide-build", build_frontend.args)
|
||||||
if self.platform != "pyodide" and build_frontend.name == "pyodide-build":
|
if self.platform != "pyodide" and build_frontend.name == "pyodide-build":
|
||||||
msg = "The 'pyodide-build' build frontend is only supported on the pyodide platform"
|
msg = "The 'pyodide-build' build frontend is only supported on the pyodide platform"
|
||||||
raise errors.ConfigurationError(msg)
|
raise errors.ConfigurationError(msg)
|
||||||
|
|||||||
+3
-3
@@ -483,9 +483,9 @@ files (from workspaces) are not supported.
|
|||||||
|
|
||||||
On Android, the "pip" frontend is not supported.
|
On Android, the "pip" frontend is not supported.
|
||||||
|
|
||||||
On Pyodide, `build-frontend` must be `pyodide-build`, which is the default for that
|
On Pyodide, `pyodide-build` is the default and only supported frontend; setting
|
||||||
platform. See [Pyodide build frontend support](platforms.md#pyodide-build-frontend) for
|
another frontend produces a warning and uses `pyodide-build` instead. See
|
||||||
details.
|
[Pyodide build frontend support](platforms.md#pyodide-build-frontend) for details.
|
||||||
|
|
||||||
You can specify extra arguments to pass to the build frontend using the
|
You can specify extra arguments to pass to the build frontend using the
|
||||||
optional `args` option.
|
optional `args` option.
|
||||||
|
|||||||
+1
-1
@@ -190,7 +190,7 @@ The `--libdir` option specifies the directory containing cross-compiled shared l
|
|||||||
|
|
||||||
### Build frontend support {: #pyodide-build-frontend}
|
### Build frontend support {: #pyodide-build-frontend}
|
||||||
|
|
||||||
The pyodide platform builds wheels by shelling out to `pyodide build`, via the `pyodide-build` [`build-frontend`](options.md#build-frontend), which itself is a meta build frontend and passes through commands to pypa/build with specialised handling. This is the only supported frontend for this platform, and is used by default.
|
The pyodide platform builds wheels by shelling out to `pyodide build`, via the `pyodide-build` [`build-frontend`](options.md#build-frontend), which itself is a meta build frontend and passes through commands to pypa/build with specialised handling. This is the only supported frontend for this platform, and is used by default. A global [`build-frontend`](options.md#build-frontend) setting naming another frontend is ignored with a warning on this platform.
|
||||||
|
|
||||||
[`build-verbosity`](options.md#build-verbosity) is passed through to `pyodide build` as `-v`/`-vv`. It is capped at `-vv`. `pyodide build` has no `-vvv` flag.
|
[`build-verbosity`](options.md#build-verbosity) is passed through to `pyodide build` as `-v`/`-vv`. It is capped at `-vv`. `pyodide build` has no `-vvv` flag.
|
||||||
|
|
||||||
|
|||||||
@@ -515,13 +515,33 @@ def test_pyodide_build_frontend_args(tmp_path: Path) -> None:
|
|||||||
assert build_frontend.args == ["--exports=whole_archive"]
|
assert build_frontend.args == ["--exports=whole_archive"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"build_frontend_str",
|
||||||
|
["default", "pip", "build", "build[uv]", "uv"],
|
||||||
|
)
|
||||||
|
def test_pyodide_global_build_frontend_coerced(tmp_path: Path, build_frontend_str: str) -> None:
|
||||||
|
"""A global non-pyodide frontend setting is coerced to pyodide-build, not an error."""
|
||||||
|
args = CommandLineArguments.defaults()
|
||||||
|
args.package_dir = tmp_path
|
||||||
|
|
||||||
|
tmp_path.joinpath("pyproject.toml").write_text(
|
||||||
|
textwrap.dedent(
|
||||||
|
f"""\
|
||||||
|
[tool.cibuildwheel]
|
||||||
|
build-frontend = "{build_frontend_str}"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
options = Options(platform="pyodide", command_line_arguments=args, env={})
|
||||||
|
build_frontend = options.build_options(identifier=None).build_frontend
|
||||||
|
|
||||||
|
assert build_frontend.name == "pyodide-build"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("platform", "build_frontend_str"),
|
("platform", "build_frontend_str"),
|
||||||
[
|
[
|
||||||
("pyodide", "pip"),
|
|
||||||
("pyodide", "build"),
|
|
||||||
("pyodide", "build[uv]"),
|
|
||||||
("pyodide", "uv"),
|
|
||||||
("linux", "pyodide-build"),
|
("linux", "pyodide-build"),
|
||||||
("macos", "pyodide-build"),
|
("macos", "pyodide-build"),
|
||||||
("windows", "pyodide-build"),
|
("windows", "pyodide-build"),
|
||||||
|
|||||||
Reference in New Issue
Block a user