Skip to content

[next] Updates and fixes to the Python wheel builder workflow #2441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions .github/workflows/python-publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ jobs:

- name: Set up QEMU
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
with:
platforms: all

- name: Build wheels
uses: pypa/cibuildwheel@v2.16.5
uses: pypa/cibuildwheel@v2.20.0
env:
CIBW_ARCHS_MACOS: "x86_64 universal2 arm64"
CIBW_ARCHS_LINUX: "x86_64 i686 aarch64" # ppc64le s390x really slow
CIBW_ARCHS_WINDOWS: "AMD64 x86" # ARM64 Seems ARM64 will rebuild amd64 wheel for unknow reason.
CIBW_ARCHS_LINUX: "x86_64 i686" # ppc64le s390x really slow
CIBW_ARCHS_WINDOWS: "AMD64" # ARM64 Seems ARM64 will rebuild amd64 wheel for unknow reason.
CIBW_BUILD: "cp38-* cp39-* cp310-* cp311-* cp312-*"
CIBW_SKIP: ""
with:
Expand All @@ -36,6 +36,17 @@ jobs:
- uses: actions/upload-artifact@v4
with:
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
Expand Down Expand Up @@ -64,16 +75,8 @@ jobs:
steps:
- uses: actions/download-artifact@v4
with:
name: artifact
path: dist

# - name: Publish distribution 📦 to test PyPI
# uses: pypa/gh-action-pypi-publish@release/v1
# with:
# user: __token__
# password: ${{ secrets.test_pypi_pass }}
# repository_url: https://test.pypi.org/legacy/

- name: Publish distribution 📦 to PyPI
if: ${{ success() }}
uses: pypa/gh-action-pypi-publish@release/v1
Expand Down
17 changes: 17 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,23 @@ endif()
set(SUPPORTED_ARCHITECTURES ARM AARCH64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X EVM MOS65XX WASM BPF RISCV SH TRICORE ALPHA HPPA LOONGARCH)
set(SUPPORTED_ARCHITECTURE_LABELS ARM AARCH64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM MOS65XX WASM BPF RISCV SH TriCore Alpha HPPA LoongArch)

# 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
2 changes: 1 addition & 1 deletion bindings/python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def build_libraries():

os.chdir(BUILD_DIR)

# platform description refers at https://docs.python.org/2/library/sys.html#sys.platform
# platform description refers at https://docs.python.org/3/library/sys.html#sys.platform
# Use cmake for both Darwin and Windows since it can generate fat binaries
if SYSTEM == "win32" or SYSTEM == 'darwin':
# Windows build: this process requires few things:
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)
Loading