Skip to content

Commit

Permalink
fix: set VSCMD_ARG_TGT_ARCH based on targeted architecture (#1876)
Browse files Browse the repository at this point in the history
* set VSCMD_ARG_TGT_ARCH based on targetted architecture

* only set VSCMD_ARG_TGT_ARCH if not already set

* add unit tests to check setuptools correctly identifies windows arch

* only run tests on windows

* arm64 fails on azure pipelines (only)

* Update windows.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Apply suggestions from code review

Co-authored-by: Joe Rickerby <[email protected]>

* update test_env_set to validate FatalError is raised on env collision

* remove noqa ARG001 (no longer needed)

---------

Co-authored-by: Henry Schreiner <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Joe Rickerby <[email protected]>
  • Loading branch information
4 people authored Jul 12, 2024
1 parent cac121a commit de84624
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 0 deletions.
10 changes: 10 additions & 0 deletions cibuildwheel/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ def setup_setuptools_cross_compile(
# set the platform name
map_plat = {"32": "win32", "64": "win-amd64", "ARM64": "win-arm64"}
plat_name = map_plat[python_configuration.arch]

# Set environment variable so that setuptools._distutils.get_platform()
# identifies the target, not the host
vscmd_arg_tgt_arch = {"32": "x86", "64": "x64", "ARM64": "arm64"}
current_tgt_arch = vscmd_arg_tgt_arch[python_configuration.arch]
if (env.get("VSCMD_ARG_TGT_ARCH") or current_tgt_arch) != current_tgt_arch:
msg = f"VSCMD_ARG_TGT_ARCH must be set to {current_tgt_arch!r}, got {env['VSCMD_ARG_TGT_ARCH']!r}. If you're setting up MSVC yourself (e.g. using vcvarsall.bat or msvc-dev-cmd), make sure to target the right architecture. Alternatively, run cibuildwheel without configuring MSVC, and let the build backend handle it."
raise errors.FatalError(msg)
env["VSCMD_ARG_TGT_ARCH"] = current_tgt_arch

# (This file must be default/locale encoding, so we can't pass 'encoding')
distutils_cfg.write_text(
textwrap.dedent(
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ test = [
"pytest-timeout",
"pytest-xdist",
"pytest>=6",
"setuptools",
"tomli_w",
"validate-pyproject",
]
Expand Down Expand Up @@ -140,6 +141,8 @@ disallow_untyped_decorators = true
[[tool.mypy.overrides]]
module = [
"setuptools",
"setuptools._distutils", # needed even if only directly import setuptools._distutils.util
"setuptools._distutils.util",
"pytest", # ignored in pre-commit to speed up check
"bashlex",
"bashlex.*",
Expand Down
92 changes: 92 additions & 0 deletions unit_test/get_platform_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import contextlib
import sys
from pathlib import Path
from typing import Dict

import pytest
import setuptools._distutils.util

from cibuildwheel.errors import FatalError
from cibuildwheel.util import CIProvider, detect_ci_provider
from cibuildwheel.windows import PythonConfiguration, setup_setuptools_cross_compile

# monkeypatching os.name is too flaky. E.g. It works on my machine, but fails in pipeline
if not sys.platform.startswith("win"):
pytest.skip("Windows-only tests", allow_module_level=True)


@contextlib.contextmanager
def patched_environment(monkeypatch: pytest.MonkeyPatch, environment: Dict[str, str]):
with monkeypatch.context() as mp:
for envvar, val in environment.items():
mp.setenv(name=envvar, value=val)
yield


def test_x86(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
arch = "32"
environment: Dict[str, str] = {}

configuration = PythonConfiguration("irrelevant", arch, "irrelevant", None)

setup_setuptools_cross_compile(tmp_path, configuration, tmp_path, environment)
with patched_environment(monkeypatch, environment):
target_platform = setuptools._distutils.util.get_platform()

assert environment["VSCMD_ARG_TGT_ARCH"] == "x86"
assert target_platform == "win32"


def test_x64(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
arch = "64"
environment: Dict[str, str] = {}

configuration = PythonConfiguration("irrelevant", arch, "irrelevant", None)

setup_setuptools_cross_compile(tmp_path, configuration, tmp_path, environment)
with patched_environment(monkeypatch, environment):
target_platform = setuptools._distutils.util.get_platform()

assert environment["VSCMD_ARG_TGT_ARCH"] == "x64"
assert target_platform == "win-amd64"


@pytest.mark.skipif(
detect_ci_provider() == CIProvider.azure_pipelines, reason="arm64 not recognised on azure"
)
def test_arm(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
arch = "ARM64"
environment: Dict[str, str] = {}

configuration = PythonConfiguration("irrelevant", arch, "irrelevant", None)

setup_setuptools_cross_compile(tmp_path, configuration, tmp_path, environment)
with patched_environment(monkeypatch, environment):
target_platform = setuptools._distutils.util.get_platform()

assert environment["VSCMD_ARG_TGT_ARCH"] == "arm64"
assert target_platform == "win-arm64"


def test_env_set(tmp_path: Path):
arch = "32"
environment = {"VSCMD_ARG_TGT_ARCH": "x64"}

configuration = PythonConfiguration("irrelevant", arch, "irrelevant", None)

with pytest.raises(FatalError, match="VSCMD_ARG_TGT_ARCH"):
setup_setuptools_cross_compile(tmp_path, configuration, tmp_path, environment)


def test_env_blank(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
arch = "32"
environment = {"VSCMD_ARG_TGT_ARCH": ""}

configuration = PythonConfiguration("irrelevant", arch, "irrelevant", None)

setup_setuptools_cross_compile(tmp_path, configuration, tmp_path, environment)
with patched_environment(monkeypatch, environment):
target_platform = setuptools._distutils.util.get_platform()

assert environment["VSCMD_ARG_TGT_ARCH"] == "x86"
assert target_platform == "win32"

0 comments on commit de84624

Please sign in to comment.