Skip ARM64 tests automatically with warning, and improved cleanup
This commit is contained in:
+107
-83
@@ -1,6 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import atexit
|
|
||||||
import os
|
import os
|
||||||
import platform as platform_module
|
import platform as platform_module
|
||||||
import shutil
|
import shutil
|
||||||
@@ -10,7 +9,7 @@ import textwrap
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Sequence
|
from typing import Callable, Sequence
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from filelock import FileLock
|
from filelock import FileLock
|
||||||
@@ -133,6 +132,7 @@ def setup_setuptools_cross_compile(
|
|||||||
python_configuration: PythonConfiguration,
|
python_configuration: PythonConfiguration,
|
||||||
python_libs_base: Path,
|
python_libs_base: Path,
|
||||||
env: dict[str, str],
|
env: dict[str, str],
|
||||||
|
cleanup_command_list: list[Callable[[], None]],
|
||||||
) -> None:
|
) -> None:
|
||||||
# We write to distutils_cfg for distutils-based builds to override some
|
# We write to distutils_cfg for distutils-based builds to override some
|
||||||
# settings. Ideally, we'd pass them on the command line, but since we don't
|
# settings. Ideally, we'd pass them on the command line, but since we don't
|
||||||
@@ -168,14 +168,14 @@ def setup_setuptools_cross_compile(
|
|||||||
f"Unable to configure setuptools for cross-compiling because existing {distutils_cfg} file cannot be backed up. Error was {exc}"
|
f"Unable to configure setuptools for cross-compiling because existing {distutils_cfg} file cannot be backed up. Error was {exc}"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
atexit.register(lambda: distutils_bak.replace(distutils_cfg))
|
cleanup_command_list.append(lambda: distutils_bak.replace(distutils_cfg))
|
||||||
elif distutils_cfg.is_dir():
|
elif distutils_cfg.is_dir():
|
||||||
log.warning(
|
log.warning(
|
||||||
f"Unable to configure setuptools for cross-compiling because {distutils_cfg} is a directory"
|
f"Unable to configure setuptools for cross-compiling because {distutils_cfg} is a directory"
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
atexit.register(lambda: distutils_cfg.unlink())
|
cleanup_command_list.append(lambda: distutils_cfg.unlink())
|
||||||
|
|
||||||
# Ensure our additional import libraries are made available, and explicitly
|
# Ensure our additional import libraries are made available, and explicitly
|
||||||
# set the platform name
|
# set the platform name
|
||||||
@@ -220,6 +220,7 @@ def setup_rust_cross_compile(
|
|||||||
python_configuration: PythonConfiguration,
|
python_configuration: PythonConfiguration,
|
||||||
python_libs_base: Path,
|
python_libs_base: Path,
|
||||||
env: dict[str, str],
|
env: dict[str, str],
|
||||||
|
cleanup_command_list: list[Callable[[], None]],
|
||||||
) -> None:
|
) -> None:
|
||||||
# Assume that MSVC will be used, because we already know that we are
|
# Assume that MSVC will be used, because we already know that we are
|
||||||
# cross-compiling. MinGW users can set CARGO_BUILD_TARGET themselves
|
# cross-compiling. MinGW users can set CARGO_BUILD_TARGET themselves
|
||||||
@@ -250,6 +251,7 @@ def setup_python(
|
|||||||
dependency_constraint_flags: Sequence[PathOrStr],
|
dependency_constraint_flags: Sequence[PathOrStr],
|
||||||
environment: ParsedEnvironment,
|
environment: ParsedEnvironment,
|
||||||
build_frontend: BuildFrontend,
|
build_frontend: BuildFrontend,
|
||||||
|
cleanup_command_list: list[Callable[[], None]],
|
||||||
) -> dict[str, str]:
|
) -> dict[str, str]:
|
||||||
tmp.mkdir()
|
tmp.mkdir()
|
||||||
implementation_id = python_configuration.identifier.split("-")[0]
|
implementation_id = python_configuration.identifier.split("-")[0]
|
||||||
@@ -371,8 +373,8 @@ def setup_python(
|
|||||||
|
|
||||||
if python_libs_base:
|
if python_libs_base:
|
||||||
# Set up the environment for various backends to enable cross-compilation
|
# Set up the environment for various backends to enable cross-compilation
|
||||||
setup_setuptools_cross_compile(python_configuration, python_libs_base, env)
|
setup_setuptools_cross_compile(python_configuration, python_libs_base, env, cleanup_command_list)
|
||||||
setup_rust_cross_compile(python_configuration, python_libs_base, env)
|
setup_rust_cross_compile(python_configuration, python_libs_base, env, cleanup_command_list)
|
||||||
|
|
||||||
return env
|
return env
|
||||||
|
|
||||||
@@ -415,6 +417,9 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
build_options.dependency_constraints.get_for_python_version(config.version),
|
build_options.dependency_constraints.get_for_python_version(config.version),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# list of callables to do any urgent cleanup, for example,
|
||||||
|
# config files that may bleed into other builds
|
||||||
|
cleanup_command_list = []
|
||||||
# install Python
|
# install Python
|
||||||
env = setup_python(
|
env = setup_python(
|
||||||
identifier_tmp_dir / "build",
|
identifier_tmp_dir / "build",
|
||||||
@@ -422,100 +427,119 @@ def build(options: Options, tmp_path: Path) -> None:
|
|||||||
dependency_constraint_flags,
|
dependency_constraint_flags,
|
||||||
build_options.environment,
|
build_options.environment,
|
||||||
build_options.build_frontend,
|
build_options.build_frontend,
|
||||||
|
cleanup_command_list,
|
||||||
)
|
)
|
||||||
|
|
||||||
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
|
try:
|
||||||
if compatible_wheel:
|
compatible_wheel = find_compatible_wheel(built_wheels, config.identifier)
|
||||||
log.step_end()
|
if compatible_wheel:
|
||||||
print(
|
log.step_end()
|
||||||
f"\nFound previously built wheel {compatible_wheel.name}, that's compatible with {config.identifier}. Skipping build step..."
|
print(
|
||||||
)
|
f"\nFound previously built wheel {compatible_wheel.name}, that's compatible with {config.identifier}. Skipping build step..."
|
||||||
repaired_wheel = compatible_wheel
|
|
||||||
else:
|
|
||||||
# run the before_build command
|
|
||||||
if build_options.before_build:
|
|
||||||
log.step("Running before_build...")
|
|
||||||
before_build_prepared = prepare_command(
|
|
||||||
build_options.before_build, project=".", package=options.globals.package_dir
|
|
||||||
)
|
)
|
||||||
shell(before_build_prepared, env=env)
|
repaired_wheel = compatible_wheel
|
||||||
|
else:
|
||||||
log.step("Building wheel...")
|
# run the before_build command
|
||||||
built_wheel_dir.mkdir()
|
if build_options.before_build:
|
||||||
|
log.step("Running before_build...")
|
||||||
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
|
before_build_prepared = prepare_command(
|
||||||
|
build_options.before_build, project=".", package=options.globals.package_dir
|
||||||
if build_options.build_frontend == "pip":
|
|
||||||
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
|
|
||||||
# see https://github.com/pypa/cibuildwheel/pull/369
|
|
||||||
call(
|
|
||||||
"python",
|
|
||||||
"-m",
|
|
||||||
"pip",
|
|
||||||
"wheel",
|
|
||||||
options.globals.package_dir.resolve(),
|
|
||||||
f"--wheel-dir={built_wheel_dir}",
|
|
||||||
"--no-deps",
|
|
||||||
*get_build_verbosity_extra_flags(build_options.build_verbosity),
|
|
||||||
env=env,
|
|
||||||
)
|
|
||||||
elif build_options.build_frontend == "build":
|
|
||||||
config_setting = " ".join(verbosity_flags)
|
|
||||||
build_env = env.copy()
|
|
||||||
if build_options.dependency_constraints:
|
|
||||||
constraints_path = (
|
|
||||||
build_options.dependency_constraints.get_for_python_version(
|
|
||||||
config.version
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
# Bug in pip <= 21.1.3 - we can't have a space in the
|
shell(before_build_prepared, env=env)
|
||||||
# constraints file, and pip doesn't support drive letters
|
|
||||||
# in uhi. After probably pip 21.2, we can use uri. For
|
|
||||||
# now, use a temporary file.
|
|
||||||
if " " in str(constraints_path):
|
|
||||||
assert " " not in str(identifier_tmp_dir)
|
|
||||||
tmp_file = identifier_tmp_dir / "constraints.txt"
|
|
||||||
tmp_file.write_bytes(constraints_path.read_bytes())
|
|
||||||
constraints_path = tmp_file
|
|
||||||
|
|
||||||
build_env["PIP_CONSTRAINT"] = str(constraints_path)
|
log.step("Building wheel...")
|
||||||
build_env["VIRTUALENV_PIP"] = get_pip_version(env)
|
built_wheel_dir.mkdir()
|
||||||
|
|
||||||
|
verbosity_flags = get_build_verbosity_extra_flags(build_options.build_verbosity)
|
||||||
|
|
||||||
|
if build_options.build_frontend == "pip":
|
||||||
|
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
|
||||||
|
# see https://github.com/pypa/cibuildwheel/pull/369
|
||||||
call(
|
call(
|
||||||
"python",
|
"python",
|
||||||
"-m",
|
"-m",
|
||||||
"build",
|
"pip",
|
||||||
build_options.package_dir,
|
"wheel",
|
||||||
"--wheel",
|
options.globals.package_dir.resolve(),
|
||||||
f"--outdir={built_wheel_dir}",
|
f"--wheel-dir={built_wheel_dir}",
|
||||||
f"--config-setting={config_setting}",
|
"--no-deps",
|
||||||
env=build_env,
|
*get_build_verbosity_extra_flags(build_options.build_verbosity),
|
||||||
|
env=env,
|
||||||
)
|
)
|
||||||
else:
|
elif build_options.build_frontend == "build":
|
||||||
assert_never(build_options.build_frontend)
|
config_setting = " ".join(verbosity_flags)
|
||||||
|
build_env = env.copy()
|
||||||
|
if build_options.dependency_constraints:
|
||||||
|
constraints_path = (
|
||||||
|
build_options.dependency_constraints.get_for_python_version(
|
||||||
|
config.version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Bug in pip <= 21.1.3 - we can't have a space in the
|
||||||
|
# constraints file, and pip doesn't support drive letters
|
||||||
|
# in uhi. After probably pip 21.2, we can use uri. For
|
||||||
|
# now, use a temporary file.
|
||||||
|
if " " in str(constraints_path):
|
||||||
|
assert " " not in str(identifier_tmp_dir)
|
||||||
|
tmp_file = identifier_tmp_dir / "constraints.txt"
|
||||||
|
tmp_file.write_bytes(constraints_path.read_bytes())
|
||||||
|
constraints_path = tmp_file
|
||||||
|
|
||||||
built_wheel = next(built_wheel_dir.glob("*.whl"))
|
build_env["PIP_CONSTRAINT"] = str(constraints_path)
|
||||||
|
build_env["VIRTUALENV_PIP"] = get_pip_version(env)
|
||||||
|
call(
|
||||||
|
"python",
|
||||||
|
"-m",
|
||||||
|
"build",
|
||||||
|
build_options.package_dir,
|
||||||
|
"--wheel",
|
||||||
|
f"--outdir={built_wheel_dir}",
|
||||||
|
f"--config-setting={config_setting}",
|
||||||
|
env=build_env,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
assert_never(build_options.build_frontend)
|
||||||
|
|
||||||
# repair the wheel
|
built_wheel = next(built_wheel_dir.glob("*.whl"))
|
||||||
repaired_wheel_dir.mkdir()
|
|
||||||
|
|
||||||
if built_wheel.name.endswith("none-any.whl"):
|
# repair the wheel
|
||||||
raise NonPlatformWheelError()
|
repaired_wheel_dir.mkdir()
|
||||||
|
|
||||||
if build_options.repair_command:
|
if built_wheel.name.endswith("none-any.whl"):
|
||||||
log.step("Repairing wheel...")
|
raise NonPlatformWheelError()
|
||||||
repair_command_prepared = prepare_command(
|
|
||||||
build_options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir
|
|
||||||
)
|
|
||||||
shell(repair_command_prepared, env=env)
|
|
||||||
else:
|
|
||||||
shutil.move(str(built_wheel), repaired_wheel_dir)
|
|
||||||
|
|
||||||
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
|
if build_options.repair_command:
|
||||||
|
log.step("Repairing wheel...")
|
||||||
|
repair_command_prepared = prepare_command(
|
||||||
|
build_options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir
|
||||||
|
)
|
||||||
|
shell(repair_command_prepared, env=env)
|
||||||
|
else:
|
||||||
|
shutil.move(str(built_wheel), repaired_wheel_dir)
|
||||||
|
|
||||||
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
|
repaired_wheel = next(repaired_wheel_dir.glob("*.whl"))
|
||||||
raise AlreadyBuiltWheelError(repaired_wheel.name)
|
|
||||||
|
if repaired_wheel.name in {wheel.name for wheel in built_wheels}:
|
||||||
|
raise AlreadyBuiltWheelError(repaired_wheel.name)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
while cleanup_command_list:
|
||||||
|
cleanup_command_list.pop(0)()
|
||||||
|
|
||||||
if build_options.test_command and options.globals.test_selector(config.identifier):
|
if build_options.test_command and options.globals.test_selector(config.identifier):
|
||||||
|
if config.arch == "ARM64" != platform_module.machine():
|
||||||
|
log.warning(
|
||||||
|
unwrap(
|
||||||
|
"""
|
||||||
|
While arm64 wheels can be built on other platforms, they cannot
|
||||||
|
be tested. An arm64 runner is required. To silence this warning,
|
||||||
|
set `CIBW_TEST_SKIP: *-win_arm64`.
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# skip this test
|
||||||
|
continue
|
||||||
|
|
||||||
log.step("Testing wheel...")
|
log.step("Testing wheel...")
|
||||||
# set up a virtual environment to install and test from, to make sure
|
# set up a virtual environment to install and test from, to make sure
|
||||||
# there are no dependencies that were pulled in at build time.
|
# there are no dependencies that were pulled in at build time.
|
||||||
|
|||||||
@@ -72,13 +72,6 @@ class TestSpam(TestCase):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
ADD_ENV: dict[str, str] = {}
|
|
||||||
|
|
||||||
if utils.platform == "windows":
|
|
||||||
if platform.machine() != "ARM64":
|
|
||||||
ADD_ENV["CIBW_TEST_SKIP"] = "*-win_arm64 " + ADD_ENV.get("CIBW_TEST_SKIP", "")
|
|
||||||
|
|
||||||
|
|
||||||
def test(tmp_path):
|
def test(tmp_path):
|
||||||
project_dir = tmp_path / "project"
|
project_dir = tmp_path / "project"
|
||||||
project_with_a_test.generate(project_dir)
|
project_with_a_test.generate(project_dir)
|
||||||
@@ -92,7 +85,6 @@ def test(tmp_path):
|
|||||||
# mac/linux.
|
# mac/linux.
|
||||||
"CIBW_TEST_COMMAND": "false || pytest {project}/test",
|
"CIBW_TEST_COMMAND": "false || pytest {project}/test",
|
||||||
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || pytest {project}/test",
|
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || pytest {project}/test",
|
||||||
**ADD_ENV,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -114,7 +106,6 @@ def test_extras_require(tmp_path):
|
|||||||
# mac/linux.
|
# mac/linux.
|
||||||
"CIBW_TEST_COMMAND": "false || pytest {project}/test",
|
"CIBW_TEST_COMMAND": "false || pytest {project}/test",
|
||||||
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || pytest {project}/test",
|
"CIBW_TEST_COMMAND_WINDOWS": "COLOR 00 || pytest {project}/test",
|
||||||
**ADD_ENV,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -152,7 +143,6 @@ def test_failing_test(tmp_path):
|
|||||||
# problems with this, so let's check that.
|
# problems with this, so let's check that.
|
||||||
"CIBW_MANYLINUX_I686_IMAGE": "manylinux1",
|
"CIBW_MANYLINUX_I686_IMAGE": "manylinux1",
|
||||||
"CIBW_MANYLINUX_X86_64_IMAGE": "manylinux1",
|
"CIBW_MANYLINUX_X86_64_IMAGE": "manylinux1",
|
||||||
**ADD_ENV,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user