1import os 2import sys 3import shutil 4 5from distutils import log 6from distutils.core import setup 7from distutils.extension import Extension 8from distutils.command.build import build 9from Cython.Distutils import build_ext 10 11SYSTEM = sys.platform 12VERSION = '4.0.0' 13 14# adapted from commit e504b81 of Nguyen Tan Cong 15# Reference: https://docs.python.org/2/library/platform.html#cross-platform 16IS_64BITS = sys.maxsize > 2**32 17 18# are we building from the repository or from a source distribution? 19ROOT_DIR = os.path.dirname(os.path.realpath(__file__)) 20LIBS_DIR = os.path.join(ROOT_DIR, 'pyx', 'lib') 21HEADERS_DIR = os.path.join(ROOT_DIR, 'pyx', 'include') 22SRC_DIR = os.path.join(ROOT_DIR, 'src') 23BUILD_DIR = SRC_DIR if os.path.exists(SRC_DIR) else os.path.join(ROOT_DIR, '../..') 24PYPACKAGE_DIR = os.path.join(ROOT_DIR, 'capstone') 25CYPACKAGE_DIR = os.path.join(ROOT_DIR, 'pyx') 26 27if SYSTEM == 'darwin': 28 VERSIONED_LIBRARY_FILE = "libcapstone.4.dylib" 29 LIBRARY_FILE = "libcapstone.dylib" 30 STATIC_LIBRARY_FILE = 'libcapstone.a' 31elif SYSTEM in ('win32', 'cygwin'): 32 VERSIONED_LIBRARY_FILE = "capstone.dll" 33 LIBRARY_FILE = "capstone.dll" 34 STATIC_LIBRARY_FILE = None 35else: 36 VERSIONED_LIBRARY_FILE = "libcapstone.so.4" 37 LIBRARY_FILE = "libcapstone.so" 38 STATIC_LIBRARY_FILE = 'libcapstone.a' 39 40compile_args = ['-O3', '-fomit-frame-pointer', '-I' + HEADERS_DIR] 41link_args = ['-L' + LIBS_DIR] 42 43ext_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' ] 44 45ext_modules = [Extension("capstone.ccapstone", 46 ["pyx/ccapstone.pyx"], 47 libraries=["capstone"], 48 extra_compile_args=compile_args, 49 extra_link_args=link_args)] 50ext_modules += [Extension("capstone.%s" % name, 51 ["pyx/%s.pyx" % name], 52 extra_compile_args=compile_args, 53 extra_link_args=link_args) 54 for name in ext_module_names] 55 56def clean_bins(): 57 shutil.rmtree(LIBS_DIR, ignore_errors=True) 58 shutil.rmtree(HEADERS_DIR, ignore_errors=True) 59 60def copy_pysources(): 61 for fname in os.listdir(PYPACKAGE_DIR): 62 if not fname.endswith('.py'): 63 continue 64 65 if fname == '__init__.py': 66 shutil.copy(os.path.join(PYPACKAGE_DIR, fname), os.path.join(CYPACKAGE_DIR, fname)) 67 else: 68 shutil.copy(os.path.join(PYPACKAGE_DIR, fname), os.path.join(CYPACKAGE_DIR, fname + 'x')) 69 70def build_libraries(): 71 """ 72 Prepare the capstone directory for a binary distribution or installation. 73 Builds shared libraries and copies header files. 74 75 Will use a src/ dir if one exists in the current directory, otherwise assumes it's in the repo 76 """ 77 cwd = os.getcwd() 78 clean_bins() 79 os.mkdir(HEADERS_DIR) 80 os.mkdir(LIBS_DIR) 81 82 # copy public headers 83 shutil.copytree(os.path.join(BUILD_DIR, 'include', 'capstone'), os.path.join(HEADERS_DIR, 'capstone')) 84 85 os.chdir(BUILD_DIR) 86 87 # platform description refers at https://docs.python.org/2/library/sys.html#sys.platform 88 if SYSTEM == "win32": 89 # Windows build: this process requires few things: 90 # - CMake + MSVC installed 91 # - Run this command in an environment setup for MSVC 92 if not os.path.exists("build"): os.mkdir("build") 93 os.chdir("build") 94 # Do not build tests & static library 95 os.system('cmake -DCMAKE_BUILD_TYPE=RELEASE -DCAPSTONE_BUILD_TESTS=0 -DCAPSTONE_BUILD_STATIC=0 -G "NMake Makefiles" ..') 96 os.system("nmake") 97 else: # Unix incl. cygwin 98 os.system("CAPSTONE_BUILD_CORE_ONLY=yes bash ./make.sh") 99 100 shutil.copy(VERSIONED_LIBRARY_FILE, os.path.join(LIBS_DIR, LIBRARY_FILE)) 101 if STATIC_LIBRARY_FILE: shutil.copy(STATIC_LIBRARY_FILE, LIBS_DIR) 102 os.chdir(cwd) 103 104 105class custom_build(build): 106 def run(self): 107 log.info('Copying python sources') 108 copy_pysources() 109 log.info('Building C extensions') 110 build_libraries() 111 return build.run(self) 112 113# clean package directory first 114#import os.path, shutil, sys 115#for f in sys.path: 116# if f.endswith('packages'): 117# pkgdir = os.path.join(f, 'capstone') 118# #print(pkgdir) 119# try: 120# shutil.rmtree(pkgdir) 121# except: 122# pass 123 124setup( 125 provides = ['capstone'], 126 package_dir = {'capstone' : 'pyx'}, 127 packages = ['capstone'], 128 name = 'capstone', 129 version = VERSION, 130 cmdclass = {'build_ext': build_ext, 'build': custom_build}, 131 ext_modules = ext_modules, 132 author = 'Nguyen Anh Quynh', 133 author_email = 'aquynh@gmail.com', 134 description = 'Capstone disassembly engine', 135 url = 'http://www.capstone-engine.org', 136 classifiers = [ 137 'License :: OSI Approved :: BSD License', 138 'Programming Language :: Python :: 2', 139 ], 140 include_package_data=True, 141 package_data={ 142 "capstone": ["lib/*", "include/capstone/*"], 143 } 144) 145