Skip to content
Snippets Groups Projects
setup.py 7.39 KiB
Newer Older
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
#!/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

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
import glob
import os
import shutil
import subprocess
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
import stat
import sys
import platform
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
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
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

VERSION = '0.9.2' + 'rc1'
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
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 in ('win32', 'cygwin'):
    LIBRARY_FILE = "keystone.dll"
else:
    LIBRARY_FILE = "libkeystone.so"
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

# prebuilt libraries for Windows - for sdist
PATH_LIB64 = os.path.join(ROOT_DIR, 'prebuilt', 'win64')
PATH_LIB32 = os.path.join(ROOT_DIR, 'prebuilt', 'win32')
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

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")))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

    for filename in src:
        outpath = os.path.join(SRC_DIR, os.path.basename(filename))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
        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)
        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):
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    def run(self):
        copy_sources()
        return _sdist.run(self)
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

class build(_build):
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    def run(self):
        log.info("Building C++ extensions")
        build_libraries()
        return _build.run(self)
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

class develop(_develop):
    def run(self):
        log.info("Building C++ extensions")
        build_libraries()
        return _develop.run(self)
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

class bdist_egg(_bdist_egg):
    def run(self):
        self.run_command('build')
        return _bdist_egg.run(self)
    
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
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('-', '_'))


with open("README.pypi-src", "r") as ld:
    long_desc = ld.read()
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

setup(
    provides=['keystone'],
    packages=['keystone'],
    name='keystone-engine',
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    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',
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    classifiers=[
        # 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',

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
        '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': ['*']
    }
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
)