2022-07-14 13:36:57 +02:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2021-01-05 19:25:25 +00:00
|
|
|
import platform
|
2021-01-24 17:50:59 +00:00
|
|
|
import subprocess
|
2021-01-05 15:14:32 +00:00
|
|
|
|
2021-01-08 15:02:20 +00:00
|
|
|
import pytest
|
|
|
|
|
|
2021-01-05 15:14:32 +00:00
|
|
|
from . import test_projects, utils
|
|
|
|
|
|
|
|
|
|
basic_project = test_projects.new_c_project()
|
|
|
|
|
|
2021-03-26 10:40:19 -04:00
|
|
|
ALL_MACOS_WHEELS = {
|
2021-05-03 11:45:43 -04:00
|
|
|
*utils.expected_wheels("spam", "0.1.0", machine_arch="x86_64"),
|
2022-08-08 18:20:57 +01:00
|
|
|
*utils.expected_wheels("spam", "0.1.0", machine_arch="arm64", include_universal2=True),
|
2021-03-26 10:40:19 -04:00
|
|
|
}
|
2021-01-06 21:33:41 +00:00
|
|
|
|
2024-06-08 10:15:04 +02:00
|
|
|
DEPLOYMENT_TARGET_TOO_LOW_WARNING = "Bumping MACOSX_DEPLOYMENT_TARGET"
|
2022-10-16 12:17:54 +01:00
|
|
|
|
2021-01-05 15:14:32 +00:00
|
|
|
|
2022-07-14 13:36:57 +02:00
|
|
|
def get_xcode_version() -> tuple[int, int]:
|
2021-02-14 12:56:33 -05:00
|
|
|
output = subprocess.run(
|
2021-05-03 11:45:43 -04:00
|
|
|
["xcodebuild", "-version"],
|
2022-07-14 12:47:01 +02:00
|
|
|
text=True,
|
2021-02-14 12:56:33 -05:00
|
|
|
check=True,
|
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
|
).stdout
|
2021-01-24 17:50:59 +00:00
|
|
|
lines = output.splitlines()
|
|
|
|
|
_, version_str = lines[0].split()
|
|
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
version_parts = version_str.split(".")
|
2021-01-26 21:52:02 +00:00
|
|
|
return (int(version_parts[0]), int(version_parts[1]))
|
2021-01-24 17:50:59 +00:00
|
|
|
|
|
|
|
|
|
2021-01-05 15:14:32 +00:00
|
|
|
def test_cross_compiled_build(tmp_path):
|
2021-05-03 11:45:43 -04:00
|
|
|
if utils.platform != "macos":
|
|
|
|
|
pytest.skip("this test is only relevant to macos")
|
2021-01-30 10:52:00 +00:00
|
|
|
if get_xcode_version() < (12, 2):
|
2021-05-03 11:45:43 -04:00
|
|
|
pytest.skip("this test only works with Xcode 12.2 or greater")
|
2021-01-05 15:14:32 +00:00
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
project_dir = tmp_path / "project"
|
2021-01-05 15:14:32 +00:00
|
|
|
basic_project.generate(project_dir)
|
|
|
|
|
|
2021-04-30 17:56:34 -04:00
|
|
|
actual_wheels = utils.cibuildwheel_run(
|
|
|
|
|
project_dir,
|
2024-05-26 12:41:20 +02:00
|
|
|
add_env={"CIBW_ARCHS": "x86_64, universal2, arm64"},
|
|
|
|
|
single_python=True,
|
2021-04-30 17:56:34 -04:00
|
|
|
)
|
2024-05-26 12:41:20 +02:00
|
|
|
python_tag = "cp{}{}".format(*utils.SINGLE_PYTHON_VERSION)
|
|
|
|
|
expected_wheels = [w for w in ALL_MACOS_WHEELS if python_tag in w]
|
2021-01-05 15:14:32 +00:00
|
|
|
assert set(actual_wheels) == set(expected_wheels)
|
|
|
|
|
|
2021-01-05 19:25:25 +00:00
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
@pytest.mark.parametrize("build_universal2", [False, True])
|
2021-01-05 19:25:25 +00:00
|
|
|
def test_cross_compiled_test(tmp_path, capfd, build_universal2):
|
2021-05-03 11:45:43 -04:00
|
|
|
if utils.platform != "macos":
|
|
|
|
|
pytest.skip("this test is only relevant to macos")
|
2021-01-30 10:52:00 +00:00
|
|
|
if get_xcode_version() < (12, 2):
|
2021-05-03 11:45:43 -04:00
|
|
|
pytest.skip("this test only works with Xcode 12.2 or greater")
|
2021-01-05 19:25:25 +00:00
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
project_dir = tmp_path / "project"
|
2021-01-05 19:25:25 +00:00
|
|
|
basic_project.generate(project_dir)
|
|
|
|
|
|
2021-04-30 17:56:34 -04:00
|
|
|
actual_wheels = utils.cibuildwheel_run(
|
|
|
|
|
project_dir,
|
|
|
|
|
add_env={
|
2024-05-26 12:41:20 +02:00
|
|
|
"CIBW_BUILD": "cp310-*" if build_universal2 else "*p310-*",
|
2021-05-03 11:45:43 -04:00
|
|
|
"CIBW_TEST_COMMAND": '''python -c "import platform; print('running tests on ' + platform.machine())"''',
|
|
|
|
|
"CIBW_ARCHS": "universal2" if build_universal2 else "x86_64 arm64",
|
2022-10-14 23:56:57 +02:00
|
|
|
"CIBW_BUILD_VERBOSITY": "3",
|
2021-04-30 17:56:34 -04:00
|
|
|
},
|
|
|
|
|
)
|
2021-01-05 19:25:25 +00:00
|
|
|
|
|
|
|
|
captured = capfd.readouterr()
|
|
|
|
|
|
2022-10-16 12:17:54 +01:00
|
|
|
assert DEPLOYMENT_TARGET_TOO_LOW_WARNING not in captured.err
|
2022-10-14 23:56:57 +02:00
|
|
|
|
2023-01-14 09:48:01 +01:00
|
|
|
platform_machine = platform.machine()
|
|
|
|
|
if platform_machine == "x86_64":
|
2021-01-05 19:25:25 +00:00
|
|
|
# ensure that tests were run on only x86_64
|
2021-05-03 11:45:43 -04:00
|
|
|
assert "running tests on x86_64" in captured.out
|
|
|
|
|
assert "running tests on arm64" not in captured.out
|
2021-01-05 19:25:25 +00:00
|
|
|
if build_universal2:
|
2021-04-30 17:56:34 -04:00
|
|
|
assert (
|
2024-02-10 09:55:38 +01:00
|
|
|
"While universal2 wheels can be built on x86_64, the arm64 part of the wheel cannot be tested"
|
2021-04-30 17:56:34 -04:00
|
|
|
in captured.err
|
|
|
|
|
)
|
2021-01-05 19:25:25 +00:00
|
|
|
else:
|
2021-04-30 17:56:34 -04:00
|
|
|
assert (
|
2021-05-03 11:45:43 -04:00
|
|
|
"While arm64 wheels can be built on x86_64, they cannot be tested" in captured.err
|
2021-04-30 17:56:34 -04:00
|
|
|
)
|
2023-01-14 09:48:01 +01:00
|
|
|
elif platform_machine == "arm64":
|
2021-01-05 19:25:25 +00:00
|
|
|
# ensure that tests were run on both x86_64 and arm64
|
2021-05-03 11:45:43 -04:00
|
|
|
assert "running tests on x86_64" in captured.out
|
|
|
|
|
assert "running tests on arm64" in captured.out
|
2023-01-14 09:48:01 +01:00
|
|
|
assert (
|
2024-02-10 09:55:38 +01:00
|
|
|
"While universal2 wheels can be built on x86_64, the arm64 part of the wheel cannot be tested"
|
2023-01-14 09:48:01 +01:00
|
|
|
not in captured.err
|
|
|
|
|
)
|
|
|
|
|
assert (
|
|
|
|
|
"While arm64 wheels can be built on x86_64, they cannot be tested" not in captured.err
|
|
|
|
|
)
|
2021-01-05 19:25:25 +00:00
|
|
|
|
2021-01-06 21:33:41 +00:00
|
|
|
if build_universal2:
|
2024-05-26 12:41:20 +02:00
|
|
|
expected_wheels = [w for w in ALL_MACOS_WHEELS if "cp310" in w and "universal2" in w]
|
2021-01-06 21:33:41 +00:00
|
|
|
else:
|
2024-05-26 12:41:20 +02:00
|
|
|
expected_wheels = [w for w in ALL_MACOS_WHEELS if "p310-" in w and "universal2" not in w]
|
2023-01-14 09:48:01 +01:00
|
|
|
if platform_machine == "x86_64":
|
2024-05-26 12:41:20 +02:00
|
|
|
expected_wheels = [w for w in expected_wheels if not ("pp310" in w and "arm64" in w)]
|
2021-01-05 19:25:25 +00:00
|
|
|
|
2021-01-06 21:33:41 +00:00
|
|
|
assert set(actual_wheels) == set(expected_wheels)
|
2021-01-26 21:52:02 +00:00
|
|
|
|
|
|
|
|
|
2022-10-16 12:17:54 +01:00
|
|
|
def test_deployment_target_warning_is_firing(tmp_path, capfd):
|
|
|
|
|
# force the warning to check that we can detect it if it happens
|
|
|
|
|
if utils.platform != "macos":
|
|
|
|
|
pytest.skip("this test is only relevant to macos")
|
|
|
|
|
|
|
|
|
|
project_dir = tmp_path / "project"
|
|
|
|
|
basic_project.generate(project_dir)
|
|
|
|
|
|
|
|
|
|
utils.cibuildwheel_run(
|
|
|
|
|
project_dir,
|
|
|
|
|
add_env={
|
|
|
|
|
"CIBW_ARCHS": "x86_64",
|
|
|
|
|
"MACOSX_DEPLOYMENT_TARGET": "10.8",
|
|
|
|
|
"CIBW_BUILD_VERBOSITY": "3",
|
|
|
|
|
},
|
2024-05-26 12:41:20 +02:00
|
|
|
single_python=True,
|
2022-10-16 12:17:54 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
captured = capfd.readouterr()
|
|
|
|
|
assert DEPLOYMENT_TARGET_TOO_LOW_WARNING in captured.err
|
|
|
|
|
|
|
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
@pytest.mark.parametrize("skip_arm64_test", [False, True])
|
2024-02-02 17:51:54 +00:00
|
|
|
def test_universal2_testing_on_x86_64(tmp_path, capfd, skip_arm64_test):
|
2021-05-03 11:45:43 -04:00
|
|
|
if utils.platform != "macos":
|
|
|
|
|
pytest.skip("this test is only relevant to macos")
|
2021-01-30 10:52:00 +00:00
|
|
|
if get_xcode_version() < (12, 2):
|
2021-05-03 11:45:43 -04:00
|
|
|
pytest.skip("this test only works with Xcode 12.2 or greater")
|
|
|
|
|
if platform.machine() != "x86_64":
|
|
|
|
|
pytest.skip("this test only works on x86_64")
|
2021-01-26 21:52:02 +00:00
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
project_dir = tmp_path / "project"
|
2021-01-26 21:52:02 +00:00
|
|
|
basic_project.generate(project_dir)
|
|
|
|
|
|
2021-04-30 17:56:34 -04:00
|
|
|
actual_wheels = utils.cibuildwheel_run(
|
|
|
|
|
project_dir,
|
|
|
|
|
add_env={
|
2021-05-03 11:45:43 -04:00
|
|
|
"CIBW_TEST_COMMAND": '''python -c "import platform; print('running tests on ' + platform.machine())"''',
|
|
|
|
|
"CIBW_ARCHS": "universal2",
|
|
|
|
|
"CIBW_TEST_SKIP": "*_universal2:arm64" if skip_arm64_test else "",
|
2021-04-30 17:56:34 -04:00
|
|
|
},
|
2024-05-26 12:41:20 +02:00
|
|
|
single_python=True,
|
2021-04-30 17:56:34 -04:00
|
|
|
)
|
2021-01-26 21:52:02 +00:00
|
|
|
|
|
|
|
|
captured = capfd.readouterr()
|
|
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
if platform.machine() == "x86_64":
|
|
|
|
|
assert "running tests on x86_64" in captured.out
|
|
|
|
|
assert "running tests on arm64" not in captured.out
|
2021-01-26 21:52:02 +00:00
|
|
|
|
2024-02-10 09:55:38 +01:00
|
|
|
warning_message = "While universal2 wheels can be built on x86_64, the arm64 part of the wheel cannot be tested"
|
2021-01-26 21:52:02 +00:00
|
|
|
if skip_arm64_test:
|
|
|
|
|
assert warning_message not in captured.err
|
|
|
|
|
else:
|
|
|
|
|
assert warning_message in captured.err
|
|
|
|
|
|
2024-05-26 12:41:20 +02:00
|
|
|
python_tag = "cp{}{}".format(*utils.SINGLE_PYTHON_VERSION)
|
|
|
|
|
expected_wheels = [w for w in ALL_MACOS_WHEELS if python_tag in w and "universal2" in w]
|
2021-01-26 21:52:02 +00:00
|
|
|
|
|
|
|
|
assert set(actual_wheels) == set(expected_wheels)
|
2022-07-14 11:42:40 +02:00
|
|
|
|
|
|
|
|
|
2024-06-09 15:45:31 -04:00
|
|
|
def test_universal2_testing_on_arm64(build_frontend_env, tmp_path, capfd):
|
2024-02-02 17:51:54 +00:00
|
|
|
# cibuildwheel should test the universal2 wheel on both x86_64 and arm64, when run on arm64
|
|
|
|
|
if utils.platform != "macos":
|
|
|
|
|
pytest.skip("this test is only relevant to macos")
|
|
|
|
|
if platform.machine() != "arm64":
|
|
|
|
|
pytest.skip("this test only works on arm64")
|
|
|
|
|
|
|
|
|
|
project_dir = tmp_path / "project"
|
|
|
|
|
basic_project.generate(project_dir)
|
|
|
|
|
|
|
|
|
|
actual_wheels = utils.cibuildwheel_run(
|
|
|
|
|
project_dir,
|
|
|
|
|
add_env={
|
|
|
|
|
"CIBW_ARCHS": "universal2",
|
|
|
|
|
# check that a native dependency is correctly installed, once per each testing arch
|
2024-06-09 15:45:31 -04:00
|
|
|
"CIBW_TEST_REQUIRES": "--only-binary :all: pillow>=10.3", # pillow>=10.3 provides wheels for macOS 10.10, not 10.9
|
|
|
|
|
"CIBW_TEST_COMMAND": '''python -c "import PIL, platform; print(f'running tests on {platform.machine()} with pillow {PIL.__version__}')"''',
|
|
|
|
|
**build_frontend_env,
|
2024-02-02 17:51:54 +00:00
|
|
|
},
|
2024-05-26 12:41:20 +02:00
|
|
|
single_python=True,
|
2024-02-02 17:51:54 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
captured = capfd.readouterr()
|
2024-06-09 15:45:31 -04:00
|
|
|
assert "running tests on arm64 with pillow" in captured.out
|
|
|
|
|
assert "running tests on x86_64 with pillow" in captured.out
|
2024-02-02 17:51:54 +00:00
|
|
|
|
2024-05-26 12:41:20 +02:00
|
|
|
python_tag = "cp{}{}".format(*utils.SINGLE_PYTHON_VERSION)
|
|
|
|
|
expected_wheels = [w for w in ALL_MACOS_WHEELS if python_tag in w and "universal2" in w]
|
2024-02-02 17:51:54 +00:00
|
|
|
assert set(actual_wheels) == set(expected_wheels)
|
|
|
|
|
|
|
|
|
|
|
2024-05-18 18:34:39 +02:00
|
|
|
def test_cp38_arm64_testing(tmp_path, capfd, request):
|
2022-07-14 11:42:40 +02:00
|
|
|
if utils.platform != "macos":
|
|
|
|
|
pytest.skip("this test is only relevant to macos")
|
|
|
|
|
if get_xcode_version() < (12, 2):
|
|
|
|
|
pytest.skip("this test only works with Xcode 12.2 or greater")
|
|
|
|
|
if platform.machine() != "arm64":
|
|
|
|
|
pytest.skip("this test only works on arm64")
|
2024-05-18 18:34:39 +02:00
|
|
|
if request.config.getoption("--run-cp38-universal2"):
|
|
|
|
|
pytest.skip("--run-cp38-universal2 option skips this test")
|
2022-07-14 11:42:40 +02:00
|
|
|
|
|
|
|
|
project_dir = tmp_path / "project"
|
|
|
|
|
basic_project.generate(project_dir)
|
|
|
|
|
|
|
|
|
|
actual_wheels = utils.cibuildwheel_run(
|
|
|
|
|
project_dir,
|
|
|
|
|
add_env={
|
|
|
|
|
"CIBW_BUILD": "cp38-*",
|
|
|
|
|
"CIBW_TEST_COMMAND": '''python -c "import platform; print('running tests on ' + platform.machine())"''',
|
|
|
|
|
"CIBW_ARCHS": "x86_64,universal2,arm64",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
captured = capfd.readouterr()
|
|
|
|
|
|
|
|
|
|
assert "running tests on x86_64" in captured.out
|
|
|
|
|
assert "running tests on arm64" not in captured.out
|
|
|
|
|
|
|
|
|
|
warning_message = "While cibuildwheel can build CPython 3.8 universal2/arm64 wheels, we cannot test the arm64 part of them"
|
|
|
|
|
assert warning_message in captured.err
|
|
|
|
|
|
|
|
|
|
expected_wheels = [w for w in ALL_MACOS_WHEELS if "cp38" in w]
|
|
|
|
|
|
|
|
|
|
assert set(actual_wheels) == set(expected_wheels)
|
2022-09-25 10:42:19 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_cp38_arm64_testing_universal2_installer(tmp_path, capfd, request):
|
|
|
|
|
if not request.config.getoption("--run-cp38-universal2"):
|
|
|
|
|
pytest.skip("needs --run-cp38-universal2 option to run")
|
|
|
|
|
|
|
|
|
|
project_dir = tmp_path / "project"
|
|
|
|
|
basic_project.generate(project_dir)
|
|
|
|
|
|
|
|
|
|
actual_wheels = utils.cibuildwheel_run(
|
|
|
|
|
project_dir,
|
|
|
|
|
add_env={
|
|
|
|
|
"CIBW_BUILD": "cp38-*",
|
|
|
|
|
"CIBW_TEST_COMMAND": '''python -c "import platform; print('running tests on ' + platform.machine())"''',
|
|
|
|
|
"CIBW_ARCHS": "x86_64,universal2,arm64",
|
|
|
|
|
"MACOSX_DEPLOYMENT_TARGET": "11.0",
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
captured = capfd.readouterr()
|
|
|
|
|
|
|
|
|
|
assert "running tests on x86_64" in captured.out
|
|
|
|
|
assert "running tests on arm64" in captured.out
|
|
|
|
|
|
|
|
|
|
warning_message = "While cibuildwheel can build CPython 3.8 universal2/arm64 wheels, we cannot test the arm64 part of them"
|
|
|
|
|
assert warning_message not in captured.err
|
|
|
|
|
|
|
|
|
|
expected_wheels = [w.replace("10_9", "11_0") for w in ALL_MACOS_WHEELS if "cp38" in w]
|
|
|
|
|
|
|
|
|
|
assert set(actual_wheels) == set(expected_wheels)
|