Newer
Older
#!/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
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
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 in ('win32', 'cygwin'):
LIBRARY_FILE = "keystone.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")))
outpath = os.path.join(SRC_DIR, os.path.basename(filename))
log.info("%s -> %s" % (filename, outpath))
shutil.copy(filename, outpath)
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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)
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):
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)
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('-', '_'))
with open("README.pypi-src", "r") as ld:
long_desc = ld.read()
setup(
provides=['keystone'],
packages=['keystone'],
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',
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 4 - Beta',
# 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=True,
include_package_data=True,
is_pure=False,
package_data={
'keystone': ['*']
}