Skip to content

Commit

Permalink
Fix: Build wheel for MacOS AArch64, x86_64 and Universal2
Browse files Browse the repository at this point in the history
  • Loading branch information
Rot127 committed Aug 15, 2024
1 parent 2487730 commit aafb191
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/python-publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ jobs:
path: ./wheelhouse/*.whl
name: artifacts-${{ matrix.os }}

- name: Check binaries (Windows)
if: matrix.os == 'windows-latest'
run: |
python3.exe suite/check_wheel_bin_arch.py ./wheelhouse/
- name: Check binaries (Unix)
if: matrix.os != 'windows-latest'
run: |
./suite/check_wheel_bin_arch.py ./wheelhouse/
make_sdist:
name: Make SDist
runs-on: ubuntu-latest
Expand Down
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ endif()
# Don't edit the makefile!
option(BUILD_SHARED_LIBS "Build shared library" OFF)
option(CAPSTONE_BUILD_STATIC_RUNTIME "Embed static runtime" ${BUILD_SHARED_LIBS})
option(CAPSTONE_BUILD_MACOS_THIN "Disable universal2 builds on macOS" OFF)
option(CAPSTONE_BUILD_DIET "Build diet library" OFF)
option(CAPSTONE_BUILD_TESTS "Build tests" ${PROJECT_IS_TOP_LEVEL})
option(CAPSTONE_BUILD_CSTOOL "Build cstool" ${PROJECT_IS_TOP_LEVEL})
Expand All @@ -48,6 +49,23 @@ option(CAPSTONE_INSTALL "Generate install target" ${PROJECT_IS_TOP_LEVEL})
set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X EVM MOS65XX WASM BPF RISCV SH TRICORE)
set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM MOS65XX WASM BPF RISCV SH TriCore)

# If building for OSX it's best to allow CMake to handle building both architectures
if(APPLE AND NOT CAPSTONE_BUILD_MACOS_THIN)
# The cibuildwheel on Github Actions sets this env variable
# with the architecture flags it wants to build for.
if(DEFINED ENV{ARCHFLAGS})
if("$ENV{ARCHFLAGS}" STREQUAL "-arch arm64 -arch x86_64")
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
elseif("$ENV{ARCHFLAGS}" STREQUAL "-arch arm64")
set(CMAKE_OSX_ARCHITECTURES "arm64")
elseif("$ENV{ARCHFLAGS}" STREQUAL "-arch x86_64")
set(CMAKE_OSX_ARCHITECTURES "x86_64")
endif()
else()
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
endif()
endif()

list(LENGTH SUPPORTED_ARCHITECTURES count)
math(EXPR count "${count}-1")
# create options controlling whether support for a particular architecture is needed
Expand Down
79 changes: 79 additions & 0 deletions suite/check_wheel_bin_arch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env python3
# Copyright © 2024 Rot127 <[email protected]>
# SPDX-License-Identifier: BSD-3

import logging as log
import subprocess as sp
import re
import os
import sys
from pathlib import Path

if len(sys.argv) != 2:
print(f"{sys.argv[0]} <wheel_dir>")
exit(-1)

log.basicConfig(
level=log.INFO,
stream=sys.stdout,
format="%(levelname)-5s - %(message)s",
force=True,
)

archs = {
"universal2": ["x86_64", "arm64"],
"x86_64": [r"x86[_-]64"],
"arm64": ["arm64"],
"aarch64": ["ARM aarch64"],
"i686": ["Intel 80386"],
"win32": [r"INVALID"],
"amd64": [r"x86[_-]64"],
}

filename = {
"macosx": "libcapstone.dylib",
"manylinux": "libcapstone.so",
"win": "capstone.dll",
}

success = True
wheel_seen = False
for root, dir, files in os.walk(sys.argv[1]):
for file in files:
f = Path(root).joinpath(file)
if f.suffix != ".whl":
continue
wheel_seen = True
target = re.search(r"py3-none-(.+).whl", f"{f}").group(1)
platform = re.search("^(win|manylinux|macosx)", target).group(1)

arch = re.search(
"(universal2|x86_64|arm64|aarch64|i686|win32|amd64)$", target
).group(1)
log.info(f"Target: {target} - Platform: {platform} - Arch: {archs[arch]}")

out_dir = f"{platform}__{arch}"
sp.run(["unzip", "-q", f"{f}", "-d", out_dir], check=True)
lib_path = Path(out_dir).joinpath(f"capstone/lib/{filename[platform]}")
result = sp.run(["file", "-b", f"{lib_path}"], capture_output=True, check=True)
stdout = result.stdout.decode("utf8").strip()
if any([not re.search(a, stdout) for a in archs[arch]]):
success = False
log.error(f"The wheel '{file}' is not compiled for '{archs[arch]}'.")
log.error(f"Binary is: {stdout}")
print()
else:
log.info(f"OK: Arch: {arch} - {lib_path}")
log.info(f"Binary is: {stdout}")
log.info(f"Delete {out_dir}")
print()
os.system(f"rm -r {out_dir}")
break

if not wheel_seen:
log.error("No wheel was checked.")
exit(-1)

if not success:
log.error("Binary files are compiled for the wrong architecture.")
exit(-1)

0 comments on commit aafb191

Please sign in to comment.