| from struct import unpack | |
| from .constants import * | |
| from .logging import * | |
| def calculate_from_build_dir(root): | |
| candidates = [ | |
| root / PYTHON_DLL_NAME, | |
| root / FREETHREADED_PYTHON_DLL_NAME, | |
| *root.glob("*.dll"), | |
| *root.glob("*.pyd"), | |
| # Check EXE last because it's easier to have cross-platform EXE | |
| *root.glob("*.exe"), | |
| ] | |
| ARCHS = { | |
| b"PE\0\0\x4c\x01": "win32", | |
| b"PE\0\0\x64\x86": "amd64", | |
| b"PE\0\0\x64\xAA": "arm64" | |
| } | |
| first_exc = None | |
| for pe in candidates: | |
| try: | |
| # Read the PE header to grab the machine type | |
| with open(pe, "rb") as f: | |
| f.seek(0x3C) | |
| offset = int.from_bytes(f.read(4), "little") | |
| f.seek(offset) | |
| arch = ARCHS[f.read(6)] | |
| except (FileNotFoundError, PermissionError, LookupError) as ex: | |
| log_debug("Failed to open {}: {}", pe, ex) | |
| continue | |
| log_info("Inferred architecture {} from {}", arch, pe) | |
| return arch |