Skip to content

Commit dd36820

Browse files
committed
bootstrap windows
1 parent bd91b15 commit dd36820

File tree

1 file changed

+66
-44
lines changed

1 file changed

+66
-44
lines changed

_build_backend/backend.py

Lines changed: 66 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -48,68 +48,90 @@ def get_requires_for_build_wheel(
4848

4949
def _bootstrap_build(temp_path: str, config_settings: dict[str, list[str] | str] | None = None) -> str:
5050
import hashlib
51+
import platform
5152
import re
5253
import shutil
5354
import subprocess
5455
import tarfile
5556
import urllib.request
57+
import zipfile
5658
from pathlib import Path
5759

5860
env = os.environ.copy()
5961
temp_path_ = Path(temp_path)
6062

61-
if "MAKE" not in env:
62-
make_path = None
63-
make_candidates = ("gmake", "make", "smake")
64-
for candidate in make_candidates:
65-
make_path = shutil.which(candidate)
66-
if make_path is not None:
67-
break
68-
if make_path is None:
69-
msg = f"Could not find a make program. Tried {make_candidates!r}"
63+
archive_dir = temp_path_
64+
if config_settings:
65+
archive_dir = Path(config_settings.get("cmake.define.CMakePythonDistributions_ARCHIVE_DOWNLOAD_DIR", archive_dir))
66+
archive_dir.mkdir(parents=True, exist_ok=True)
67+
68+
if os.name == "posix":
69+
if "MAKE" not in env:
70+
make_path = None
71+
make_candidates = ("gmake", "make", "smake")
72+
for candidate in make_candidates:
73+
make_path = shutil.which(candidate)
74+
if make_path is not None:
75+
break
76+
if make_path is None:
77+
msg = f"Could not find a make program. Tried {make_candidates!r}"
78+
raise ValueError(msg)
79+
env["MAKE"] = make_path
80+
make_path = env["MAKE"]
81+
kind = "unix_source"
82+
else:
83+
assert os.name == "nt"
84+
machine = platform.machine()
85+
kinds = {
86+
"x86": "win32_binary",
87+
"AMD64": "win64_binary",
88+
"ARM64": "winarm64_binary",
89+
}
90+
if machine not in kinds:
91+
msg = f"Could not find CMake required to build on a {machine} system"
7092
raise ValueError(msg)
71-
env["MAKE"] = make_path
72-
make_path = env["MAKE"]
93+
kind = kinds[machine]
7394

74-
archive_path = temp_path_
75-
if config_settings:
76-
archive_path = Path(config_settings.get("cmake.define.CMakePythonDistributions_ARCHIVE_DOWNLOAD_DIR", archive_path))
77-
archive_path.mkdir(parents=True, exist_ok=True)
7895

7996
cmake_urls = Path("CMakeUrls.cmake").read_text()
80-
source_url = re.findall(r'set\(unix_source_url\s+"(?P<data>.*)"\)$', cmake_urls, flags=re.MULTILINE)[0]
81-
source_sha256 = re.findall(r'set\(unix_source_sha256\s+"(?P<data>.*)"\)$', cmake_urls, flags=re.MULTILINE)[0]
97+
archive_url = re.findall(rf'set\({kind}_url\s+"(?P<data>.*)"\)$', cmake_urls, flags=re.MULTILINE)[0]
98+
archive_sha256 = re.findall(rf'set\({kind}_sha256\s+"(?P<data>.*)"\)$', cmake_urls, flags=re.MULTILINE)[0]
8299

83-
tarball_name = source_url.rsplit("/", maxsplit=1)[1]
84-
assert tarball_name.endswith(".tar.gz")
85-
source_tarball = archive_path / tarball_name
86-
if not source_tarball.exists():
100+
archive_name = source_url.rsplit("/", maxsplit=1)[1]
101+
archive_path = archive_dir / archive_name
102+
if not archive_path.exists():
87103
with urllib.request.urlopen(source_url) as response:
88-
source_tarball.write_bytes(response.read())
104+
archive_path.write_bytes(response.read())
89105

90-
sha256 = hashlib.sha256(source_tarball.read_bytes()).hexdigest()
91-
if source_sha256.lower() != sha256.lower():
92-
msg = f"Invalid sha256 for {source_url!r}. Expected {source_sha256!r}, got {sha256!r}"
106+
sha256 = hashlib.sha256(archive_path.read_bytes()).hexdigest()
107+
if archive_sha256.lower() != sha256.lower():
108+
msg = f"Invalid sha256 for {archive_url!r}. Expected {archive_sha256!r}, got {sha256!r}"
93109
raise ValueError(msg)
94110

95-
tar_filter_kwargs = {"filter": "tar"} if hasattr(tarfile, "tar_filter") else {}
96-
with tarfile.open(source_tarball) as tar:
97-
tar.extractall(path=temp_path_, **tar_filter_kwargs)
98-
99-
parallel_str = env.get("CMAKE_BUILD_PARALLEL_LEVEL", "1")
100-
parallel = max(0, int(parallel_str) if parallel_str.isdigit() else 1) or os.cpu_count() or 1
101-
102-
bootstrap_path = next(temp_path_.glob("cmake-*/bootstrap"))
103-
prefix_path = temp_path_ / "cmake-install"
104-
bootstrap_args = [f"--prefix={prefix_path}", "--no-qt-gui", "--no-debugger", "--parallel={parallel}"]
105-
previous_cwd = Path().absolute()
106-
os.chdir(bootstrap_path.parent)
107-
try:
108-
subprocess.run([bootstrap_path, *bootstrap_args], env=env, check=True)
109-
subprocess.run([make_path, "-j", f"{parallel}"], env=env, check=True)
110-
subprocess.run([make_path, "install"], env=env, check=True)
111-
finally:
112-
os.chdir(previous_cwd)
111+
if os.name == "posix":
112+
assert archive_name.endswith(".tar.gz")
113+
tar_filter_kwargs = {"filter": "tar"} if hasattr(tarfile, "tar_filter") else {}
114+
with tarfile.open(archive_path) as tar:
115+
tar.extractall(path=temp_path_, **tar_filter_kwargs)
116+
117+
parallel_str = env.get("CMAKE_BUILD_PARALLEL_LEVEL", "1")
118+
parallel = max(0, int(parallel_str) if parallel_str.isdigit() else 1) or os.cpu_count() or 1
119+
120+
bootstrap_path = next(temp_path_.glob("cmake-*/bootstrap"))
121+
prefix_path = temp_path_ / "cmake-install"
122+
bootstrap_args = [f"--prefix={prefix_path}", "--no-qt-gui", "--no-debugger", "--parallel={parallel}"]
123+
previous_cwd = Path().absolute()
124+
os.chdir(bootstrap_path.parent)
125+
try:
126+
subprocess.run([bootstrap_path, *bootstrap_args], env=env, check=True)
127+
subprocess.run([make_path, "-j", f"{parallel}"], env=env, check=True)
128+
subprocess.run([make_path, "install"], env=env, check=True)
129+
finally:
130+
os.chdir(previous_cwd)
131+
else:
132+
assert archive_name.endswith(".zip")
133+
with zipfile.ZipFile(archive_path) as zip_:
134+
zip_.extractall(path=prefix_path)
113135

114136
return str(prefix_path / "bin" / "cmake")
115137

@@ -124,7 +146,7 @@ def build_wheel(
124146
try:
125147
return _orig.build_wheel(wheel_directory, config_settings, metadata_directory)
126148
except CMakeNotFoundError:
127-
if os.name != "posix":
149+
if os.name not in {"posix", "nt"}:
128150
raise
129151
# Let's try bootstrapping CMake
130152
import tempfile

0 commit comments

Comments
 (0)