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 = '4.0.0' # 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.4.dylib" 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.4" 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' ] 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] 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") # Do not build tests & static library os.system('cmake -DCMAKE_BUILD_TYPE=RELEASE -DCAPSTONE_BUILD_TESTS=0 -DCAPSTONE_BUILD_STATIC=0 -G "NMake Makefiles" ..') os.system("nmake") 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', ], include_package_data=True, package_data={ "capstone": ["lib/*", "include/capstone/*"], } )