Skip to content
Snippets Groups Projects
setup.py 6.44 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 stat
import sys
from distutils import dir_util, file_util
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
from distutils import log
from distutils.command.build_clib import build_clib
from distutils.command.install_lib import install_lib
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
from distutils.command.sdist import sdist
from distutils.core import setup

# prebuilt libraries for Windows - for sdist
PATH_LIB64 = "prebuilt/win64/keystone.dll"
PATH_LIB32 = "prebuilt/win32/keystone.dll"

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
# package name can be 'keystone-engine' or 'keystone-engine-windows'
PKG_NAME = 'keystone-engine'
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
if os.path.exists(PATH_LIB64) and os.path.exists(PATH_LIB32):
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    PKG_NAME = 'keystone-engine-windows'
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
SYSTEM = sys.platform

SETUP_DATA_FILES = []

# 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

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 = []

    try:
        dir_util.remove_tree("src/")
    except (IOError, OSError):
        pass

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    dir_util.copy_tree("../../llvm", "src/llvm/")
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    dir_util.copy_tree("../../include", "src/include/")
    dir_util.copy_tree("../../suite", "src/suite")
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

    src.extend(glob.glob("../../*.h"))
    src.extend(glob.glob("../../*.cpp"))
    src.extend(glob.glob("../../*.inc"))
    src.extend(glob.glob("../../*.def"))

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    src.extend(glob.glob("../../CMakeLists.txt"))
    src.extend(glob.glob("../../CMakeUninstall.in"))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    src.extend(glob.glob("../../*.txt"))
    src.extend(glob.glob("../../*.TXT"))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    src.extend(glob.glob("../../COPYING"))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    src.extend(glob.glob("../../LICENSE*"))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    src.extend(glob.glob("../../EXCEPTIONS-CLIENT"))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    src.extend(glob.glob("../../README.md"))
    src.extend(glob.glob("../../RELEASE_NOTES"))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    src.extend(glob.glob("../../ChangeLog"))
    src.extend(glob.glob("../../SPONSORS.TXT"))
    src.extend(glob.glob("../../*.cmake"))
    src.extend(glob.glob("../../*.sh"))
    src.extend(glob.glob("../../*.bat"))
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

    for filename in src:
        outpath = os.path.join("./src/", os.path.basename(filename))
        log.info("%s -> %s" % (filename, outpath))
        shutil.copy(filename, outpath)


class custom_sdist(sdist):
    """Reshuffle files for distribution."""

    def run(self):
        # if prebuilt libraries are existent, then do not copy source
        if os.path.exists(PATH_LIB64) and os.path.exists(PATH_LIB32):
            return sdist.run(self)
        copy_sources()
        return sdist.run(self)


class custom_build_clib(build_clib):
    """Customized build_clib command."""

    def run(self):
        log.info('running custom_build_clib')
        build_clib.run(self)

    def finalize_options(self):
        # We want build-clib to default to build-lib as defined by the "build"
        # command.  This is so the compiled library will be put in the right
        # place along side the python code.
        self.set_undefined_options('build',
                                   ('build_lib', 'build_clib'),
                                   ('build_temp', 'build_temp'),
                                   ('compiler', 'compiler'),
                                   ('debug', 'debug'),
                                   ('force', 'force'))

        build_clib.finalize_options(self)

    def build_libraries(self, libraries):

        cur_dir = os.path.realpath(os.curdir)

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
        if SYSTEM in ("win32", "cygwin"):
            # if Windows prebuilt library is available, then include it
            if is_64bits and os.path.exists(PATH_LIB64):
                SETUP_DATA_FILES.append(PATH_LIB64)
                return
            elif os.path.exists(PATH_LIB32):
                SETUP_DATA_FILES.append(PATH_LIB32)
                return

        try:
            for (lib_name, build_info) in libraries:
                log.info("building '%s' library", lib_name)

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
                # cd src/build
                if not os.path.isdir('build'):
                    os.mkdir('build')
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
                os.chdir("build")
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

                # platform description refers at https://docs.python.org/2/library/sys.html#sys.platform
                if SYSTEM == "cygwin":
                    os.chmod("make.sh", stat.S_IREAD | stat.S_IEXEC)
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
                    if is_64bits:
                        os.system("KEYSTONE_BUILD_CORE_ONLY=yes ./make.sh cygwin-mingw64")
                    else:
                        os.system("KEYSTONE_BUILD_CORE_ONLY=yes ./make.sh cygwin-mingw32")
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
                    SETUP_DATA_FILES.append("src/build/keystone.dll")
                else:  # Unix
                    os.chmod("../make-share.sh", stat.S_IREAD | stat.S_IEXEC)
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
                    os.system("../make-share.sh lib_only")
                    base_dir = os.path.realpath(os.curdir)
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
                    if SYSTEM == "darwin":
                        SETUP_DATA_FILES.append(base_dir + "/llvm/lib/libkeystone.dylib")
                        SETUP_DATA_FILES.append(base_dir + "/llvm/lib/libkeystone.so")
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed

Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
                # back to root dir
                os.chdir(cur_dir)

        except Exception as e:
            log.error(e)
        finally:
            os.chdir(cur_dir)


class custom_install(install_lib):
    def install(self):
        install_lib.install(self)
        ks_install_dir = os.path.join(self.install_dir, 'keystone')
        for lib_file in SETUP_DATA_FILES:
            file_util.copy_file(lib_file, ks_install_dir)
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed


def dummy_src():
    return []


setup(
    provides=['keystone'],
    packages=['keystone'],
    name=PKG_NAME,
    version=VERSION,
    author='Nguyen Anh Quynh',
    author_email='aquynh@gmail.com',
    description='Keystone assembler engine',
    url='http://www.keystone-engine.org',
    classifiers=[
        'License :: OSI Approved :: BSD License',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 3',
    ],
    requires=['ctypes'],
    cmdclass=dict(
        build_clib=custom_build_clib,
        sdist=custom_sdist,
        install_lib=custom_install,
Nguyen Anh Quynh's avatar
Nguyen Anh Quynh committed
    ),

    libraries=[(
        'keystone', dict(
            package='keystone',
            sources=dummy_src()
        ),
    )],
)