Remove deprecated packaging and cython (#2400)

* Remove deprecated packaging and cython

* Fix some issues after cherry-picking

* Fix CI issues

* Remove test files added for v6

* Also remove test_alpha.py
This commit is contained in:
Kevin Phoenix 2024-07-23 23:18:26 -07:00 committed by GitHub
parent e90ef3928f
commit 1bd2a32f2a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 81 additions and 718 deletions

View file

@ -1,10 +1,10 @@
name: Run Test
on:
on:
push:
paths-ignore:
- ".gitignore"
- "docs/**"
- "ChangeLog"
- "ChangeLog"
- "CREDITS.TXT"
- "COMPILE.TXT"
- "COMPILE_MSVC.TXT"
@ -30,46 +30,29 @@ jobs:
matrix:
config:
- {
name: 'ubuntu-20.04 x64 python3.6 cmake',
os: ubuntu-20.04,
name: 'ubuntu-22.04 x64 make',
os: ubuntu-22.04,
arch: x64,
python-arch: x64,
python-version: '3.6',
build-system: 'cmake',
build-system: 'make',
}
- {
name: 'ubuntu-22.04 x64 python3.9 make',
name: 'ubuntu-22.04 x64 cmake',
os: ubuntu-22.04,
arch: x64,
python-arch: x64,
python-version: '3.9',
build-system: 'make',
}
- {
name: 'ubuntu-22.04 x64 python3.9 cmake',
os: ubuntu-22.04,
arch: x64,
python-arch: x64,
python-version: '3.9',
build-system: 'cmake',
}
enable-asan: 'OFF'
}
- {
name: 'ubuntu-22.04 x64 python3.11 cmake',
os: ubuntu-22.04,
name: 'ubuntu-22.04 x64 ASAN',
os: ubuntu-latest,
arch: x64,
python-arch: x64,
python-version: '3.11',
build-system: 'cmake',
enable-asan: 'ON'
}
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.config.python-version }}
- name: prepare
shell: 'script -q -e -c "bash {0}"'
run: |
@ -135,7 +118,7 @@ jobs:
- name: '🛠️ Win MSVC 64 setup'
if: contains(matrix.config.name, 'MSVC 64')
uses: ilammy/msvc-dev-cmd@v1
uses: ilammy/msvc-dev-cmd@v1
with:
arch: 'x64'

View file

@ -21,3 +21,5 @@ jobs:
with:
name: artifacts
path: ./out/artifacts
- name: Install Python Dependencies
run: python -m pip install --upgrade setuptools build wheel

32
.github/workflows/python-tests.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Python Package CI
on:
push:
pull_request:
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, windows-2022, macOS-14]
python-version: ["3.8", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Setup MSVC
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
- name: Build and install capstone
run: pip install ./bindings/python
- name: Run tests
run: python ./bindings/python/tests/test_all.py

1
.gitignore vendored
View file

@ -25,6 +25,7 @@
# python
bindings/python/build/
bindings/python/capstone.egg-info/
bindings/cython/capstone.egg-info/
*.pyc
# java

View file

@ -13,45 +13,7 @@
To control the install destination, set the DESTDIR environment variable.
2. For better Python performance, install cython-based binding with:
$ sudo make install_cython
Note that this requires Cython installed first. To install Cython, see
below.
3. To install Cython, you have to ensure that the header files
and the static library for Python are installed beforehand.
E.g. on Ubuntu, do:
$ sudo apt-get install python-dev
Depending on if you already have pip or easy_install installed, install
Cython with either:
$ sudo pip install cython
or:
$ sudo easy_install cython
NOTE: Depending on your distribution you might also be able to
install the required Cython version using your repository.
E.g. on Ubuntu, do:
$ sudo apt-get install cython
However, our cython-based binding requires Cython version 0.19 or newer,
but sometimes distributions only provide older version. Make sure to
verify the current installed version before going into section 2 above.
E.g, on Ubuntu, you can verify the current Cython version with:
$ apt-cache policy cython
Which should at least print version 0.19
4. This directory contains some test code to show how to use the Capstone API.
2. The tests directory contains some test code to show how to use the Capstone API.
- test_basic.py
This code shows the most simple form of API where we only want to get basic

View file

@ -1,7 +1,7 @@
PYTHON2 ?= python2
PYTHON3 ?= python3
.PHONY: gen_const install install3 install_cython sdist sdist3 bdist bdist3 clean check
.PHONY: gen_const install sdist bdist clean check
gen_const:
cd .. && $(PYTHON2) const_generator.py python
@ -22,23 +22,6 @@ install3:
$(PYTHON3) setup.py build install; \
fi
# NOTE: Newer cython can be installed by: sudo pip install --upgrade cython
install_cython:
rm -rf src/
if test -n "${DESTDIR}"; then \
$(PYTHON2) setup_cython.py build install --root="${DESTDIR}"; \
else \
$(PYTHON2) setup_cython.py build install; \
fi
install3_cython:
rm -rf src/
if test -n "${DESTDIR}"; then \
$(PYTHON3) setup_cython.py build install --root="${DESTDIR}"; \
else \
$(PYTHON3) setup_cython.py build install; \
fi
# build & upload PyPi package with source code of the core
sdist:
rm -rf src/ dist/

View file

@ -348,10 +348,16 @@ CS_OPT = {v:k for k,v in locals().items() if k.startswith('CS_OPT_')}
import ctypes, ctypes.util
from os.path import split, join, dirname
import distutils.sysconfig
import pkg_resources
import sysconfig
from pathlib import PurePath
import inspect
if sys.version_info >= (3, 9):
import importlib.resources as resources
else:
import importlib_resources as resources
if not hasattr(sys.modules[__name__], '__file__'):
__file__ = inspect.getfile(inspect.currentframe())
@ -379,17 +385,17 @@ _cs = None
# Loading attempts, in order
# - user-provided environment variable
# - pkg_resources can get us the path to the local libraries
# - importlib.resources can get us the path to the local libraries
# - we can get the path to the local libraries by parsing our filename
# - global load
# - python's lib directory
# - last-gasp attempt at some hardcoded paths on darwin and linux
_path_list = [os.getenv('LIBCAPSTONE_PATH', None),
pkg_resources.resource_filename(__name__, 'lib'),
str(resources.files(__name__) / "lib"),
join(split(__file__)[0], 'lib'),
'',
distutils.sysconfig.get_python_lib(),
sysconfig.get_path('platlib'),
"/usr/local/lib/" if sys.platform == 'darwin' else '/usr/lib64']
for _path in _path_list:

View file

@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

View file

@ -1 +0,0 @@
This directory contains Cython files.

View file

@ -1,72 +0,0 @@
# By Dang Hoang Vu <danghvu@gmail.com>, 2014
from libcpp cimport bool
from libc.stdint cimport uint8_t, uint64_t, uint16_t
cdef extern from "<capstone/capstone.h>":
ctypedef size_t csh
ctypedef enum cs_mode:
pass
ctypedef enum cs_arch:
pass
ctypedef struct cs_detail:
pass
ctypedef struct cs_insn:
unsigned int id
uint64_t address
uint16_t size
uint8_t bytes[24]
char mnemonic[32]
char op_str[160]
cs_detail *detail
ctypedef enum cs_err:
pass
ctypedef enum cs_opt_type:
pass
unsigned int cs_version(int *major, int *minor)
bool cs_support(int arch)
cs_err cs_open(cs_arch arch, cs_mode mode, csh *handle)
cs_err cs_close(csh *handle)
cs_err cs_errno(csh handle)
size_t cs_disasm(csh handle,
const uint8_t *code, size_t code_size,
uint64_t address,
size_t count,
cs_insn **insn)
cs_err cs_option(csh handle, cs_opt_type type, size_t value)
void cs_free(cs_insn *insn, size_t count)
const char *cs_reg_name(csh handle, unsigned int reg_id)
const char *cs_insn_name(csh handle, unsigned int insn_id)
const char *cs_group_name(csh handle, unsigned int group_id)
bool cs_insn_group(csh handle, cs_insn *insn, unsigned int group_id)
bool cs_reg_read(csh handle, cs_insn *insn, unsigned int reg_id)
bool cs_reg_write(csh handle, cs_insn *insn, unsigned int reg_id)
int cs_op_count(csh handle, cs_insn *insn, unsigned int op_type)
cs_err cs_regs_access(csh handle, cs_insn *insn, uint16_t *regs_read, uint8_t *read_count, uint16_t *regs_write, uint8_t *write_count)
int cs_op_index(csh handle, cs_insn *insn, unsigned int op_type,
unsigned int position)

View file

@ -1,386 +0,0 @@
# By Dang Hoang Vu <danghvu@gmail.com>, 2014
cimport pyx.ccapstone as cc
import capstone, ctypes
from . import arm, x86, mips, ppc, arm64, sparc, systemz, xcore, tms320c64x, m68k, m680x, evm, mos65xx, wasm, bpf, riscv, sh, tricore, CsError
_diet = cc.cs_support(capstone.CS_SUPPORT_DIET)
class CsDetail(object):
def __init__(self, arch, raw_detail = None):
if not raw_detail:
return
detail = ctypes.cast(raw_detail, ctypes.POINTER(capstone._cs_detail)).contents
self.regs_read = detail.regs_read
self.regs_read_count = detail.regs_read_count
self.regs_write = detail.regs_write
self.regs_write_count = detail.regs_write_count
self.groups = detail.groups
self.groups_count = detail.groups_count
self.writeback = detail.writeback
if arch == capstone.CS_ARCH_ARM:
(self.usermode, self.vector_size, self.vector_data, self.cps_mode, self.cps_flag, \
self.cc, self.update_flags, self.writeback, self.post_index, self.mem_barrier, self.operands) = \
arm.get_arch_info(detail.arch.arm)
elif arch == capstone.CS_ARCH_ARM64:
(self.cc, self.update_flags, self.writeback, self.post_index, self.operands) = \
arm64.get_arch_info(detail.arch.arm64)
elif arch == capstone.CS_ARCH_X86:
(self.prefix, self.opcode, self.rex, self.addr_size, \
self.modrm, self.sib, self.disp, \
self.sib_index, self.sib_scale, self.sib_base, \
self.xop_cc, self.sse_cc, self.avx_cc, self.avx_sae, self.avx_rm, \
self.eflags, self.fpu_flags, self.encoding, self.modrm_offset, self.disp_offset, \
self.disp_size, self.imm_offset, self.imm_size, self.operands) = x86.get_arch_info(detail.arch.x86)
elif arch == capstone.CS_ARCH_M68K:
(self.operands, self.op_size) = m68k.get_arch_info(detail.arch.m68k)
elif arch == capstone.CS_ARCH_MIPS:
self.operands = mips.get_arch_info(detail.arch.mips)
elif arch == capstone.CS_ARCH_PPC:
(self.bc, self.bh, self.update_cr0, self.operands) = \
ppc.get_arch_info(detail.arch.ppc)
elif arch == capstone.CS_ARCH_SPARC:
(self.cc, self.hint, self.operands) = sparc.get_arch_info(detail.arch.sparc)
elif arch == capstone.CS_ARCH_SYSZ:
(self.cc, self.operands) = systemz.get_arch_info(detail.arch.sysz)
elif arch == capstone.CS_ARCH_XCORE:
self.operands = xcore.get_arch_info(detail.arch.xcore)
elif arch == capstone.CS_ARCH_TMS320C64X:
(self.condition, self.funit, self.parallel, self.operands) = tms320c64x.get_arch_info(self._detail.arch.tms320c64x)
elif arch == capstone.CS_ARCH_M680X:
(self.flags, self.operands) = m680x.get_arch_info(detail.arch.m680x)
elif arch == capstone.CS_ARCH_EVM:
(self.pop, self.push, self.fee) = evm.get_arch_info(detail.arch.evm)
elif arch == capstone.CS_ARCH_MOS65XX:
(self.am, self.modifies_flags, self.operands) = mos65xx.get_arch_info(detail.arch.mos65xx)
elif arch == capstone.CS_ARCH_WASM:
(self.operands) = wasm.get_arch_info(detail.arch.wasm)
elif arch == capstone.CS_ARCH_BPF:
(self.operands) = bpf.get_arch_info(detail.arch.bpf)
elif arch == capstone.CS_ARCH_RISCV:
(self.need_effective_addr, self.operands) = riscv.get_arch_info(detail.arch.riscv)
elif arch == capstone.CS_ARCH_SH:
(self.sh_insn, self.sh_size, self.operands) = sh.get_arch_info(detail.arch.sh)
elif arch == capstone.CS_ARCH_TRICORE:
(self.update_flags, self.operands) = tricore.get_arch_info(detail.arch.tricore)
cdef class CsInsn(object):
cdef cc.cs_insn _raw
cdef cc.csh _csh
cdef object _detail
def __cinit__(self, _detail):
self._detail = _detail
# defer to CsDetail structure for everything else.
def __getattr__(self, name):
_detail = self._detail
if not _detail:
raise CsError(capstone.CS_ERR_DETAIL)
return getattr(_detail, name)
# return instruction's operands.
@property
def operands(self):
return self._detail.operands
# return instruction's ID.
@property
def id(self):
return self._raw.id
# return instruction's address.
@property
def address(self):
return self._raw.address
# return instruction's size.
@property
def size(self):
return self._raw.size
# return instruction's machine bytes (which should have @size bytes).
@property
def bytes(self):
return bytearray(self._raw.bytes[:self._raw.size])
# return instruction's mnemonic.
@property
def mnemonic(self):
if _diet:
# Diet engine cannot provide @mnemonic & @op_str
raise CsError(capstone.CS_ERR_DIET)
return self._raw.mnemonic
# return instruction's operands (in string).
@property
def op_str(self):
if _diet:
# Diet engine cannot provide @mnemonic & @op_str
raise CsError(capstone.CS_ERR_DIET)
return self._raw.op_str
# return list of all implicit registers being read.
@property
def regs_read(self):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
if _diet:
# Diet engine cannot provide @regs_read
raise CsError(capstone.CS_ERR_DIET)
if self._detail:
detail = self._detail
return detail.regs_read[:detail.regs_read_count]
raise CsError(capstone.CS_ERR_DETAIL)
# return list of all implicit registers being modified
@property
def regs_write(self):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
if _diet:
# Diet engine cannot provide @regs_write
raise CsError(capstone.CS_ERR_DIET)
if self._detail:
detail = self._detail
return detail.regs_write[:detail.regs_write_count]
raise CsError(capstone.CS_ERR_DETAIL)
# return list of semantic groups this instruction belongs to.
@property
def groups(self):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
if _diet:
# Diet engine cannot provide @groups
raise CsError(capstone.CS_ERR_DIET)
if self._detail:
detail = self._detail
return detail.groups[:detail.groups_count]
raise CsError(capstone.CS_ERR_DETAIL)
# get the last error code
def errno(self):
return cc.cs_errno(self._csh)
# get the register name, given the register ID
def reg_name(self, reg_id):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
if _diet:
# Diet engine cannot provide register's name
raise CsError(capstone.CS_ERR_DIET)
return cc.cs_reg_name(self._csh, reg_id)
# get the instruction string
def insn_name(self):
if _diet:
# Diet engine cannot provide instruction's name
raise CsError(capstone.CS_ERR_DIET)
return cc.cs_insn_name(self._csh, self.id)
# get the group string
def group_name(self, group_id):
if _diet:
# Diet engine cannot provide group's name
raise CsError(capstone.CS_ERR_DIET)
return cc.cs_group_name(self._csh, group_id)
# verify if this insn belong to group with id as @group_id
def group(self, group_id):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
if _diet:
# Diet engine cannot provide @groups
raise CsError(capstone.CS_ERR_DIET)
return group_id in self.groups
# verify if this instruction implicitly read register @reg_id
def reg_read(self, reg_id):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
if _diet:
# Diet engine cannot provide @regs_read
raise CsError(capstone.CS_ERR_DIET)
return reg_id in self.regs_read
# verify if this instruction implicitly modified register @reg_id
def reg_write(self, reg_id):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
if _diet:
# Diet engine cannot provide @regs_write
raise CsError(capstone.CS_ERR_DIET)
return reg_id in self.regs_write
# return number of operands having same operand type @op_type
def op_count(self, op_type):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
c = 0
for op in self._detail.operands:
if op.type == op_type:
c += 1
return c
# get the operand at position @position of all operands having the same type @op_type
def op_find(self, op_type, position):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
c = 0
for op in self._detail.operands:
if op.type == op_type:
c += 1
if c == position:
return op
# Return (list-of-registers-read, list-of-registers-modified) by this instructions.
# This includes all the implicit & explicit registers.
def regs_access(self):
if self._raw.id == 0:
raise CsError(capstone.CS_ERR_SKIPDATA)
cdef cc.uint16_t regs_read[64]
cdef cc.uint16_t regs_write[64]
cdef cc.uint8_t read_count, write_count
status = cc.cs_regs_access(self._cs.csh, &self._raw, regs_read, &read_count, regs_write, &write_count)
if status != capstone.CS_ERR_OK:
raise CsError(status)
r1 = []
for i from 0 <= i < read_count: r1.append(regs_read[i])
w1 = []
for i from 0 <= i < write_count: w1.append(regs_write[i])
return (r1, w1)
cdef class Cs(object):
cdef cc.csh _csh
cdef object _cs
def __cinit__(self, _cs):
cdef version = cc.cs_version(NULL, NULL)
if (version != (capstone.CS_API_MAJOR << 8) + capstone.CS_API_MINOR):
# our binding version is different from the core's API version
raise CsError(capstone.CS_ERR_VERSION)
self._csh = <cc.csh> _cs.csh.value
self._cs = _cs
# destructor to be called automatically when object is destroyed.
def __dealloc__(self):
if self._csh:
status = cc.cs_close(&self._csh)
if status != capstone.CS_ERR_OK:
raise CsError(status)
# Disassemble binary & return disassembled instructions in CsInsn objects
def disasm(self, code, addr, count=0):
cdef cc.cs_insn *allinsn
cdef res = cc.cs_disasm(self._csh, code, len(code), addr, count, &allinsn)
detail = self._cs.detail
arch = self._cs.arch
try:
for i from 0 <= i < res:
if detail:
dummy = CsInsn(CsDetail(arch, <size_t>allinsn[i].detail))
else:
dummy = CsInsn(None)
dummy._raw = allinsn[i]
dummy._csh = self._csh
yield dummy
finally:
cc.cs_free(allinsn, res)
# Light function to disassemble binary. This is about 20% faster than disasm() because
# unlike disasm(), disasm_lite() only return tuples of (address, size, mnemonic, op_str),
# rather than CsInsn objects.
def disasm_lite(self, code, addr, count=0):
# TODO: dont need detail, so we might turn off detail, then turn on again when done
cdef cc.cs_insn *allinsn
if _diet:
# Diet engine cannot provide @mnemonic & @op_str
raise CsError(capstone.CS_ERR_DIET)
cdef res = cc.cs_disasm(self._csh, code, len(code), addr, count, &allinsn)
try:
for i from 0 <= i < res:
insn = allinsn[i]
yield (insn.address, insn.size, insn.mnemonic, insn.op_str)
finally:
cc.cs_free(allinsn, res)
# print out debugging info
def debug():
if cc.cs_support(capstone.CS_SUPPORT_DIET):
diet = "diet"
else:
diet = "standard"
archs = { "arm": capstone.CS_ARCH_ARM, "arm64": capstone.CS_ARCH_ARM64, \
"m68k": capstone.CS_ARCH_M68K, "mips": capstone.CS_ARCH_MIPS, \
"ppc": capstone.CS_ARCH_PPC, "sparc": capstone.CS_ARCH_SPARC, \
"sysz": capstone.CS_ARCH_SYSZ, "xcore": capstone.CS_ARCH_XCORE, \
"tms320c64x": capstone.CS_ARCH_TMS320C64X, "m680x": capstone.CS_ARCH_M680X, \
"evm": capstone.CS_ARCH_EVM, "mos65xx": capstone.CS_ARCH_MOS65XX, \
"wasm": capstone.CS_ARCH_WASM, \
"bpf": capstone.CS_ARCH_BPF, "riscv": capstone.CS_ARCH_RISCV, \
"sh": capstone.CS_ARCH_SH, "tricore": capstone.CS_ARCH_TRICORE }
all_archs = ""
keys = list(archs.keys())
keys.sort()
for k in keys:
if cc.cs_support(archs[k]):
all_archs += "-%s" %k
if cc.cs_support(capstone.CS_ARCH_X86):
all_archs += "-x86"
if cc.cs_support(capstone.CS_SUPPORT_X86_REDUCE):
all_archs += "_reduce"
(major, minor, _combined) = capstone.cs_version()
return "Cython-%s%s-c%u.%u-b%u.%u" %(diet, all_archs, major, minor, capstone.CS_API_MAJOR, capstone.CS_API_MINOR)

View file

@ -6,16 +6,15 @@ import shutil
import sys
import platform
from distutils import log
import logging
from setuptools import setup
from distutils.util import get_platform
from distutils.command.build import build
from distutils.command.sdist import sdist
from sysconfig import get_platform
from setuptools.command.build import build
from setuptools.command.sdist import sdist
from setuptools.command.bdist_egg import bdist_egg
PYTHON2 = sys.version_info[0] == 2
if PYTHON2:
import io
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
SYSTEM = sys.platform
@ -106,7 +105,7 @@ def copy_sources():
for filename in src:
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
log.info("%s -> %s" % (filename, outpath))
logger.info("%s -> %s" % (filename, outpath))
shutil.copy(filename, outpath)
def build_libraries():
@ -127,6 +126,7 @@ def build_libraries():
# if prebuilt libraries are available, use those and cancel build
if os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE)) and \
(not STATIC_LIBRARY_FILE or os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', STATIC_LIBRARY_FILE))):
logger.info('Using prebuilt libraries')
shutil.copy(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE), LIBS_DIR)
if STATIC_LIBRARY_FILE is not None:
shutil.copy(os.path.join(ROOT_DIR, 'prebuilt', STATIC_LIBRARY_FILE), LIBS_DIR)
@ -165,9 +165,9 @@ class custom_sdist(sdist):
class custom_build(build):
def run(self):
if 'LIBCAPSTONE_PATH' in os.environ:
log.info('Skipping building C extensions since LIBCAPSTONE_PATH is set')
logger.info('Skipping building C extensions since LIBCAPSTONE_PATH is set')
else:
log.info('Building C extensions')
logger.info('Building C extensions')
build_libraries()
return build.run(self)
@ -189,7 +189,7 @@ try:
from setuptools.command.develop import develop
class custom_develop(develop):
def run(self):
log.info("Building C extensions")
logger.info("Building C extensions")
build_libraries()
return develop.run(self)
@ -220,19 +220,20 @@ setup(
author_email='aquynh@gmail.com',
description='Capstone disassembly engine',
url='https://www.capstone-engine.org',
long_description=io.open('README.txt', encoding="utf8").read() if PYTHON2 else open('README.txt', encoding="utf8").read(),
long_description=open('README.txt', encoding="utf8").read(),
long_description_content_type='text/markdown',
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
python_requires='>=3.8',
classifiers=[
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
],
cmdclass=cmdclass,
zip_safe=True,
zip_safe=False,
include_package_data=True,
package_data={
"capstone": ["lib/*", "include/capstone/*"],
}
},
install_requires=[
"importlib_resources;python_version<'3.9'",
],
)

View file

@ -1,151 +0,0 @@
import os
import sys
import shutil
from distutils import log
from distutils.core import setup
from distutils.extension import Extension
from distutils.command.build import build
from Cython.Distutils import build_ext
SYSTEM = sys.platform
VERSION = '5.0.0'
VERSION_PARTS = VERSION.split(".")
# adapted from commit e504b81 of Nguyen Tan Cong
# Reference: https://docs.python.org/2/library/platform.html#cross-platform
IS_64BITS = sys.maxsize > 2**32
# are we building from the repository or from a source distribution?
ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
LIBS_DIR = os.path.join(ROOT_DIR, 'pyx', 'lib')
HEADERS_DIR = os.path.join(ROOT_DIR, 'pyx', 'include')
SRC_DIR = os.path.join(ROOT_DIR, 'src')
BUILD_DIR = SRC_DIR if os.path.exists(SRC_DIR) else os.path.join(ROOT_DIR, '../..')
PYPACKAGE_DIR = os.path.join(ROOT_DIR, 'capstone')
CYPACKAGE_DIR = os.path.join(ROOT_DIR, 'pyx')
if SYSTEM == 'darwin':
VERSIONED_LIBRARY_FILE = "libcapstone.{}.dylib".format(VERSION_PARTS[0])
LIBRARY_FILE = "libcapstone.dylib"
STATIC_LIBRARY_FILE = 'libcapstone.a'
elif SYSTEM in ('win32', 'cygwin'):
VERSIONED_LIBRARY_FILE = "capstone.dll"
LIBRARY_FILE = "capstone.dll"
STATIC_LIBRARY_FILE = None
else:
VERSIONED_LIBRARY_FILE = "libcapstone.so.{}".format(VERSION_PARTS[0])
LIBRARY_FILE = "libcapstone.so"
STATIC_LIBRARY_FILE = 'libcapstone.a'
compile_args = ['-O3', '-fomit-frame-pointer', '-I' + HEADERS_DIR]
link_args = ['-L' + LIBS_DIR]
ext_module_names = ['arm', 'arm_const', 'arm64', 'arm64_const', 'm68k', 'm68k_const', 'm680x', 'm680x_const', 'mips', 'mips_const', 'ppc', 'ppc_const', 'x86', 'x86_const', 'sparc', 'sparc_const', 'systemz', 'sysz_const', 'xcore', 'xcore_const', 'tms320c64x', 'tms320c64x_const', 'evm', 'evm_const', 'mos65xx', 'mos65xx_const', 'wasm', 'wasm_const', 'bpf', 'bpf_const', 'riscv', 'riscv_const', 'sh', 'sh_const', 'tricore', 'tricore_const' ]
ext_modules = [Extension("capstone.ccapstone",
["pyx/ccapstone.pyx"],
libraries=["capstone"],
extra_compile_args=compile_args,
extra_link_args=link_args)]
ext_modules += [Extension("capstone.%s" % name,
["pyx/%s.pyx" % name],
extra_compile_args=compile_args,
extra_link_args=link_args)
for name in ext_module_names]
for e in ext_modules:
e.cython_directives = {"language_level": str(sys.version_info[0])}
def clean_bins():
shutil.rmtree(LIBS_DIR, ignore_errors=True)
shutil.rmtree(HEADERS_DIR, ignore_errors=True)
def copy_pysources():
for fname in os.listdir(PYPACKAGE_DIR):
if not fname.endswith('.py'):
continue
if fname == '__init__.py':
shutil.copy(os.path.join(PYPACKAGE_DIR, fname), os.path.join(CYPACKAGE_DIR, fname))
else:
shutil.copy(os.path.join(PYPACKAGE_DIR, fname), os.path.join(CYPACKAGE_DIR, fname + 'x'))
def build_libraries():
"""
Prepare the capstone directory for a binary distribution or installation.
Builds shared libraries and copies header files.
Will use a src/ dir if one exists in the current directory, otherwise assumes it's in the repo
"""
cwd = os.getcwd()
clean_bins()
os.mkdir(HEADERS_DIR)
os.mkdir(LIBS_DIR)
# copy public headers
shutil.copytree(os.path.join(BUILD_DIR, 'include', 'capstone'), os.path.join(HEADERS_DIR, 'capstone'))
os.chdir(BUILD_DIR)
# platform description refers at https://docs.python.org/2/library/sys.html#sys.platform
if SYSTEM == "win32":
# Windows build: this process requires few things:
# - CMake + MSVC installed
# - Run this command in an environment setup for MSVC
if not os.path.exists("build"): os.mkdir("build")
os.chdir("build")
# Only build capstone.dll
os.system('cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_SHARED=ON -DCAPSTONE_BUILD_TESTS=OFF -DCAPSTONE_BUILD_CSTOOL=OFF -G "NMake Makefiles" ..')
os.system("cmake --build .")
else: # Unix incl. cygwin
os.system("CAPSTONE_BUILD_CORE_ONLY=yes bash ./make.sh")
shutil.copy(VERSIONED_LIBRARY_FILE, os.path.join(LIBS_DIR, LIBRARY_FILE))
if STATIC_LIBRARY_FILE: shutil.copy(STATIC_LIBRARY_FILE, LIBS_DIR)
os.chdir(cwd)
class custom_build(build):
def run(self):
log.info('Copying python sources')
copy_pysources()
log.info('Building C extensions')
build_libraries()
return build.run(self)
# clean package directory first
#import os.path, shutil, sys
#for f in sys.path:
# if f.endswith('packages'):
# pkgdir = os.path.join(f, 'capstone')
# #print(pkgdir)
# try:
# shutil.rmtree(pkgdir)
# except:
# pass
setup(
provides = ['capstone'],
package_dir = {'capstone' : 'pyx'},
packages = ['capstone'],
name = 'capstone',
version = VERSION,
cmdclass = {'build_ext': build_ext, 'build': custom_build},
ext_modules = ext_modules,
author = 'Nguyen Anh Quynh',
author_email = 'aquynh@gmail.com',
description = 'Capstone disassembly engine',
url = 'http://www.capstone-engine.org',
classifiers = [
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
],
include_package_data=True,
package_data={
"capstone": ["lib/*", "include/capstone/*"],
}
)