| 3 | from .logging import * |
| 4 | |
| 5 | def calculate_from_build_dir(root): |
| 6 | candidates = [ |
| 7 | root / PYTHON_DLL_NAME, |
| 8 | root / FREETHREADED_PYTHON_DLL_NAME, |
| 9 | *root.glob("*.dll"), |
| 10 | *root.glob("*.pyd"), |
| 11 | # Check EXE last because it's easier to have cross-platform EXE |
| 12 | *root.glob("*.exe"), |
| 13 | ] |
| 14 | |
| 15 | ARCHS = { |
| 16 | b"PE\0\0\x4c\x01": "win32", |
| 17 | b"PE\0\0\x64\x86": "amd64", |
| 18 | b"PE\0\0\x64\xAA": "arm64" |
| 19 | } |
| 20 | |
| 21 | first_exc = None |
| 22 | for pe in candidates: |
| 23 | try: |
| 24 | # Read the PE header to grab the machine type |
| 25 | with open(pe, "rb") as f: |
| 26 | f.seek(0x3C) |
| 27 | offset = int.from_bytes(f.read(4), "little") |
| 28 | f.seek(offset) |
| 29 | arch = ARCHS[f.read(6)] |
| 30 | except (FileNotFoundError, PermissionError, LookupError) as ex: |
| 31 | log_debug("Failed to open {}: {}", pe, ex) |
| 32 | continue |
| 33 | log_info("Inferred architecture {} from {}", arch, pe) |
| 34 | return arch |