You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
8.7 KiB
244 lines
8.7 KiB
3 years ago
|
#!/usr/bin/env python
|
||
|
# Python binding for Keystone engine. Nguyen Anh Quynh <aquynh@gmail.com>
|
||
|
|
||
|
# upload TestPyPi package with: $ python setup.py sdist upload -r pypitest
|
||
|
# upload PyPi package with: $ python setup.py sdist upload -r pypi
|
||
|
|
||
|
import glob
|
||
|
import os
|
||
|
import shutil
|
||
|
import subprocess
|
||
|
import stat
|
||
|
import sys
|
||
|
import platform
|
||
|
from distutils import log
|
||
|
from setuptools import setup
|
||
|
from distutils.util import get_platform
|
||
|
from distutils.command.build import build as _build
|
||
|
from distutils.command.sdist import sdist as _sdist
|
||
|
from setuptools.command.bdist_egg import bdist_egg as _bdist_egg
|
||
|
from setuptools.command.develop import develop as _develop
|
||
|
|
||
|
#VERSION = '0.9.2' + 'rc1' + '.post2'
|
||
|
VERSION = '0.9.2'
|
||
|
SYSTEM = sys.platform
|
||
|
IS_64BITS = platform.architecture()[0] == '64bit'
|
||
|
|
||
|
# paths
|
||
|
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||
|
LIBS_DIR = os.path.join(ROOT_DIR, 'keystone')
|
||
|
SRC_DIR = os.path.join(ROOT_DIR, 'src')
|
||
|
BUILD_DIR = os.path.join(SRC_DIR, 'build')
|
||
|
|
||
|
if SYSTEM == 'darwin':
|
||
|
LIBRARY_FILE = "libkeystone.dylib"
|
||
|
MAC_LIBRARY_FILE = "libkeystone*.dylib"
|
||
|
elif SYSTEM == 'win32':
|
||
|
LIBRARY_FILE = "keystone.dll"
|
||
|
elif SYSTEM == 'cygwin':
|
||
|
LIBRARY_FILE = "cygkeystone-0.dll"
|
||
|
else:
|
||
|
LIBRARY_FILE = "libkeystone.so"
|
||
|
|
||
|
# prebuilt libraries for Windows - for sdist
|
||
|
PATH_LIB64 = os.path.join(ROOT_DIR, 'prebuilt', 'win64')
|
||
|
PATH_LIB32 = os.path.join(ROOT_DIR, 'prebuilt', 'win32')
|
||
|
|
||
|
def copy_sources():
|
||
|
"""Copy the C sources into the source directory.
|
||
|
This rearranges the source files under the python distribution
|
||
|
directory.
|
||
|
"""
|
||
|
src = []
|
||
|
|
||
|
os.system('make clean')
|
||
|
shutil.rmtree(SRC_DIR, ignore_errors=True)
|
||
|
os.mkdir(SRC_DIR)
|
||
|
|
||
|
shutil.copytree(os.path.join(ROOT_DIR, '../../llvm'), os.path.join(SRC_DIR, 'llvm/'))
|
||
|
shutil.copytree(os.path.join(ROOT_DIR, '../../include'), os.path.join(SRC_DIR, 'include/'))
|
||
|
shutil.copytree(os.path.join(ROOT_DIR, '../../suite'), os.path.join(SRC_DIR, 'suite/'))
|
||
|
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.h")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.cpp")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.inc")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.def")))
|
||
|
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../CMakeLists.txt")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../CMakeUninstall.in")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.txt")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.TXT")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../COPYING")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../LICENSE*")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../EXCEPTIONS-CLIENT")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../README.md")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../RELEASE_NOTES")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../ChangeLog")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../SPONSORS.TXT")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.cmake")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.sh")))
|
||
|
src.extend(glob.glob(os.path.join(ROOT_DIR, "../../*.bat")))
|
||
|
|
||
|
for filename in src:
|
||
|
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
|
||
|
log.info("%s -> %s" % (filename, outpath))
|
||
|
shutil.copy(filename, outpath)
|
||
|
|
||
|
def build_libraries():
|
||
|
cur_dir = os.getcwd()
|
||
|
|
||
|
if SYSTEM in ("win32", "cygwin"):
|
||
|
# if Windows prebuilt library is available, then include it
|
||
|
if IS_64BITS and os.path.exists(os.path.join(PATH_LIB64, LIBRARY_FILE)):
|
||
|
shutil.copy(os.path.join(PATH_LIB64, LIBRARY_FILE), LIBS_DIR)
|
||
|
return
|
||
|
elif os.path.exists(os.path.join(PATH_LIB32, LIBRARY_FILE)):
|
||
|
shutil.copy(os.path.join(PATH_LIB32, LIBRARY_FILE), LIBS_DIR)
|
||
|
return
|
||
|
# cd src/build
|
||
|
if not os.path.isdir(SRC_DIR):
|
||
|
copy_sources()
|
||
|
os.chdir(SRC_DIR)
|
||
|
if not os.path.isdir(BUILD_DIR):
|
||
|
os.mkdir(BUILD_DIR)
|
||
|
os.chdir(BUILD_DIR)
|
||
|
|
||
|
if SYSTEM == "win32":
|
||
|
if IS_64BITS:
|
||
|
subprocess.call([r'..\nmake-dll.bat'])
|
||
|
else:
|
||
|
subprocess.call([r'..\nmake-dll.bat', 'X86'])
|
||
|
winobj_dir = os.path.join(BUILD_DIR, 'llvm', 'bin')
|
||
|
shutil.copy(os.path.join(winobj_dir, LIBRARY_FILE), LIBS_DIR)
|
||
|
else:
|
||
|
cmd = ['sh', '../make-share.sh', 'lib_only']
|
||
|
subprocess.call(cmd)
|
||
|
if SYSTEM == "cygwin":
|
||
|
obj_dir = os.path.join(BUILD_DIR, 'llvm', 'bin')
|
||
|
else:
|
||
|
obj_dir = os.path.join(BUILD_DIR, 'llvm', 'lib')
|
||
|
obj64_dir = os.path.join(BUILD_DIR, 'llvm', 'lib64')
|
||
|
if SYSTEM == 'darwin':
|
||
|
for file in glob.glob(os.path.join(obj_dir, MAC_LIBRARY_FILE)):
|
||
|
try:
|
||
|
shutil.copy(file, LIBS_DIR, follow_symlinks=False)
|
||
|
except:
|
||
|
shutil.copy(file, LIBS_DIR)
|
||
|
else:
|
||
|
try:
|
||
|
shutil.copy(os.path.join(obj_dir, LIBRARY_FILE), LIBS_DIR)
|
||
|
except:
|
||
|
shutil.copy(os.path.join(obj64_dir, LIBRARY_FILE), LIBS_DIR)
|
||
|
# back to root dir
|
||
|
os.chdir(cur_dir)
|
||
|
|
||
|
class sdist(_sdist):
|
||
|
def run(self):
|
||
|
copy_sources()
|
||
|
return _sdist.run(self)
|
||
|
|
||
|
class build(_build):
|
||
|
def run(self):
|
||
|
log.info("Building C++ extensions")
|
||
|
build_libraries()
|
||
|
return _build.run(self)
|
||
|
|
||
|
class develop(_develop):
|
||
|
def run(self):
|
||
|
log.info("Building C++ extensions")
|
||
|
build_libraries()
|
||
|
return _develop.run(self)
|
||
|
|
||
|
class bdist_egg(_bdist_egg):
|
||
|
def run(self):
|
||
|
self.run_command('build')
|
||
|
return _bdist_egg.run(self)
|
||
|
|
||
|
def dummy_src():
|
||
|
return []
|
||
|
|
||
|
if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
||
|
idx = sys.argv.index('bdist_wheel') + 1
|
||
|
sys.argv.insert(idx, '--plat-name')
|
||
|
name = get_platform()
|
||
|
if 'linux' in name:
|
||
|
# linux_* platform tags are disallowed because the python ecosystem is fubar
|
||
|
# linux builds should be built in the centos 5 vm for maximum compatibility
|
||
|
# see https://github.com/pypa/manylinux
|
||
|
# see also https://github.com/angr/angr-dev/blob/master/bdist.sh
|
||
|
sys.argv.insert(idx + 1, 'manylinux1_' + platform.machine())
|
||
|
elif 'mingw' in name:
|
||
|
if IS_64BITS:
|
||
|
sys.argv.insert(idx + 1, 'win_amd64')
|
||
|
else:
|
||
|
sys.argv.insert(idx + 1, 'win32')
|
||
|
else:
|
||
|
# https://www.python.org/dev/peps/pep-0425/
|
||
|
sys.argv.insert(idx + 1, name.replace('.', '_').replace('-', '_'))
|
||
|
|
||
|
|
||
|
long_desc = '''
|
||
|
Keystone is a lightweight multi-platform, multi-architecture assembler framework.
|
||
|
It offers some unparalleled features:
|
||
|
|
||
|
- Multi-architecture, with support for Arm, Arm64 (AArch64/Armv8), Ethereum Virtual Machine, Hexagon, Mips, PowerPC, Sparc, SystemZ & X86 (include 16/32/64bit).
|
||
|
- Clean/simple/lightweight/intuitive architecture-neutral API.
|
||
|
- Implemented in C/C++ languages, with bindings for Java, Masm, C#, PowerShell, Perl, Python, NodeJS, Ruby, Go, Rust, Haskell, VB6 & OCaml available.
|
||
|
- Native support for Windows & \*nix (with Mac OSX, Linux, \*BSD & Solaris confirmed).
|
||
|
- Thread-safe by design.
|
||
|
- Open source - with a dual license.
|
||
|
|
||
|
Further information is available at http://www.keystone-engine.org
|
||
|
|
||
|
|
||
|
License
|
||
|
-------
|
||
|
|
||
|
Keystone is available under a dual license:
|
||
|
|
||
|
- Version 2 of the GNU General Public License (GPLv2). (I.e. Without the "any later version" clause.).
|
||
|
License information can be found in the COPYING file EXCEPTIONS-CLIENT file.
|
||
|
|
||
|
This combination allows almost all of open source projects to use Keystone without conflicts.
|
||
|
|
||
|
- For commercial usage in production environments, contact the authors of Keystone to buy a royalty-free license.
|
||
|
|
||
|
See LICENSE-COM.TXT for more information.
|
||
|
'''
|
||
|
|
||
|
setup(
|
||
|
provides=['keystone'],
|
||
|
packages=['keystone'],
|
||
|
name='keystone-engine',
|
||
|
version=VERSION,
|
||
|
author='Nguyen Anh Quynh',
|
||
|
author_email='aquynh@gmail.com',
|
||
|
description='Keystone assembler engine',
|
||
|
long_description=long_desc,
|
||
|
long_description_content_type="text/markdown",
|
||
|
url='https://www.keystone-engine.org',
|
||
|
classifiers=[
|
||
|
# How mature is this project? Common values are
|
||
|
# 3 - Alpha
|
||
|
# 4 - Beta
|
||
|
# 5 - Production/Stable
|
||
|
'Development Status :: 5 - Production/Stable',
|
||
|
|
||
|
# Indicate who your project is intended for
|
||
|
'Intended Audience :: Developers',
|
||
|
'Topic :: Software Development :: Build Tools',
|
||
|
|
||
|
'License :: OSI Approved :: BSD License',
|
||
|
'Programming Language :: Python :: 2',
|
||
|
'Programming Language :: Python :: 3',
|
||
|
],
|
||
|
requires=['ctypes'],
|
||
|
cmdclass={'build': build, 'develop': develop, 'sdist': sdist, 'bdist_egg': bdist_egg},
|
||
|
zip_safe=False,
|
||
|
include_package_data=True,
|
||
|
is_pure=False,
|
||
|
package_data={
|
||
|
'keystone': ['*']
|
||
|
}
|
||
|
)
|