Rizin
unix-like reverse engineering framework and cli tools
setup.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import glob
4 import os
5 import shutil
6 import sys
7 import platform
8 
9 from distutils import log
10 from setuptools import setup
11 from distutils.util import get_platform
12 from distutils.command.build import build
13 from distutils.command.sdist import sdist
14 from setuptools.command.bdist_egg import bdist_egg
15 
16 SYSTEM = sys.platform
17 
18 # adapted from commit e504b81 of Nguyen Tan Cong
19 # Reference: https://docs.python.org/2/library/platform.html#cross-platform
20 IS_64BITS = sys.maxsize > 2**32
21 
22 # are we building from the repository or from a source distribution?
23 ROOT_DIR = os.path.dirname(os.path.realpath(__file__))
24 LIBS_DIR = os.path.join(ROOT_DIR, 'capstone', 'lib')
25 HEADERS_DIR = os.path.join(ROOT_DIR, 'capstone', 'include')
26 SRC_DIR = os.path.join(ROOT_DIR, 'src')
27 BUILD_DIR = SRC_DIR if os.path.exists(SRC_DIR) else os.path.join(ROOT_DIR, '../..')
28 
29 # Parse version from pkgconfig.mk
30 VERSION_DATA = {}
31 with open(os.path.join(BUILD_DIR, 'pkgconfig.mk')) as fp:
32  lines = fp.readlines()
33  for line in lines:
34  line = line.strip()
35  if len(line) == 0:
36  continue
37  if line.startswith('#'):
38  continue
39  if '=' not in line:
40  continue
41 
42  k, v = line.split('=', 1)
43  k = k.strip()
44  v = v.strip()
45  if len(k) == 0 or len(v) == 0:
46  continue
47  VERSION_DATA[k] = v
48 
49 if 'PKG_MAJOR' not in VERSION_DATA or \
50  'PKG_MINOR' not in VERSION_DATA or \
51  'PKG_EXTRA' not in VERSION_DATA:
52  raise Exception("Malformed pkgconfig.mk")
53 
54 if 'PKG_TAG' in VERSION_DATA:
55  VERSION = '{PKG_MAJOR}.{PKG_MINOR}.{PKG_EXTRA}.{PKG_TAG}'.format(**VERSION_DATA)
56 else:
57  VERSION = '{PKG_MAJOR}.{PKG_MINOR}.{PKG_EXTRA}'.format(**VERSION_DATA)
58 
59 if SYSTEM == 'darwin':
60  VERSIONED_LIBRARY_FILE = "libcapstone.{PKG_MAJOR}.dylib".format(**VERSION_DATA)
61  LIBRARY_FILE = "libcapstone.dylib"
62  STATIC_LIBRARY_FILE = 'libcapstone.a'
63 elif SYSTEM in ('win32', 'cygwin'):
64  VERSIONED_LIBRARY_FILE = "capstone.dll"
65  LIBRARY_FILE = "capstone.dll"
66  STATIC_LIBRARY_FILE = None
67 else:
68  VERSIONED_LIBRARY_FILE = "libcapstone.so.{PKG_MAJOR}".format(**VERSION_DATA)
69  LIBRARY_FILE = "libcapstone.so"
70  STATIC_LIBRARY_FILE = 'libcapstone.a'
71 
72 def clean_bins():
73  shutil.rmtree(LIBS_DIR, ignore_errors=True)
74  shutil.rmtree(HEADERS_DIR, ignore_errors=True)
75 
77  """Copy the C sources into the source directory.
78  This rearranges the source files under the python distribution
79  directory.
80  """
81  src = []
82 
83  try:
84  shutil.rmtree("src/")
85  except (IOError, OSError):
86  pass
87 
88  shutil.copytree(os.path.join(BUILD_DIR, "arch"), os.path.join(SRC_DIR, "arch"))
89  shutil.copytree(os.path.join(BUILD_DIR, "include"), os.path.join(SRC_DIR, "include"))
90 
91  src.extend(glob.glob(os.path.join(BUILD_DIR, "*.[ch]")))
92  src.extend(glob.glob(os.path.join(BUILD_DIR, "*.mk")))
93 
94  src.extend(glob.glob(os.path.join(BUILD_DIR, "Makefile")))
95  src.extend(glob.glob(os.path.join(BUILD_DIR, "LICENSE*")))
96  src.extend(glob.glob(os.path.join(BUILD_DIR, "README")))
97  src.extend(glob.glob(os.path.join(BUILD_DIR, "*.TXT")))
98  src.extend(glob.glob(os.path.join(BUILD_DIR, "RELEASE_NOTES")))
99  src.extend(glob.glob(os.path.join(BUILD_DIR, "make.sh")))
100  src.extend(glob.glob(os.path.join(BUILD_DIR, "CMakeLists.txt")))
101  src.extend(glob.glob(os.path.join(BUILD_DIR, "pkgconfig.mk")))
102 
103  for filename in src:
104  outpath = os.path.join(SRC_DIR, os.path.basename(filename))
105  log.info("%s -> %s" % (filename, outpath))
106  shutil.copy(filename, outpath)
107 
109  """
110  Prepare the capstone directory for a binary distribution or installation.
111  Builds shared libraries and copies header files.
112 
113  Will use a src/ dir if one exists in the current directory, otherwise assumes it's in the repo
114  """
115  cwd = os.getcwd()
116  clean_bins()
117  os.mkdir(HEADERS_DIR)
118  os.mkdir(LIBS_DIR)
119 
120  # copy public headers
121  shutil.copytree(os.path.join(BUILD_DIR, 'include', 'capstone'), os.path.join(HEADERS_DIR, 'capstone'))
122 
123  # if prebuilt libraries are available, use those and cancel build
124  if os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE)) and \
125  (not STATIC_LIBRARY_FILE or os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', STATIC_LIBRARY_FILE))):
126  shutil.copy(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE), LIBS_DIR)
127  if STATIC_LIBRARY_FILE is not None:
128  shutil.copy(os.path.join(ROOT_DIR, 'prebuilt', STATIC_LIBRARY_FILE), LIBS_DIR)
129  return
130 
131  os.chdir(BUILD_DIR)
132 
133  # platform description refers at https://docs.python.org/2/library/sys.html#sys.platform
134  if SYSTEM == "win32":
135  # Windows build: this process requires few things:
136  # - CMake + MSVC installed
137  # - Run this command in an environment setup for MSVC
138  if not os.path.exists("build"): os.mkdir("build")
139  os.chdir("build")
140  # Do not build tests & static library
141  os.system('cmake -DCMAKE_BUILD_TYPE=RELEASE -DCAPSTONE_BUILD_TESTS=0 -DCAPSTONE_BUILD_STATIC=0 -G "NMake Makefiles" ..')
142  os.system("nmake")
143  else: # Unix incl. cygwin
144  os.system("CAPSTONE_BUILD_CORE_ONLY=yes bash ./make.sh")
145 
146  shutil.copy(VERSIONED_LIBRARY_FILE, os.path.join(LIBS_DIR, LIBRARY_FILE))
147 
148  # only copy static library if it exists (it's a build option)
149  if STATIC_LIBRARY_FILE and os.path.exists(STATIC_LIBRARY_FILE):
150  shutil.copy(STATIC_LIBRARY_FILE, LIBS_DIR)
151  os.chdir(cwd)
152 
153 
154 class custom_sdist(sdist):
155  def run(self):
156  clean_bins()
157  copy_sources()
158  return sdist.run(self)
159 
160 
162  def run(self):
163  if 'LIBCAPSTONE_PATH' in os.environ:
164  log.info('Skipping building C extensions since LIBCAPSTONE_PATH is set')
165  else:
166  log.info('Building C extensions')
168  return build.run(self)
169 
170 
171 class custom_bdist_egg(bdist_egg):
172  def run(self):
173  self.run_command('build')
174  return bdist_egg.run(self)
175 
176 def dummy_src():
177  return []
178 
179 cmdclass = {}
180 cmdclass['build'] = custom_build
181 cmdclass['sdist'] = custom_sdist
182 cmdclass['bdist_egg'] = custom_bdist_egg
183 
184 try:
185  from setuptools.command.develop import develop
186  class custom_develop(develop):
187  def run(self):
188  log.info("Building C extensions")
190  return develop.run(self)
191 
192  cmdclass['develop'] = custom_develop
193 except ImportError:
194  print("Proper 'develop' support unavailable.")
195 
196 if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
197  idx = sys.argv.index('bdist_wheel') + 1
198  sys.argv.insert(idx, '--plat-name')
199  name = get_platform()
200  if 'linux' in name:
201  # linux_* platform tags are disallowed because the python ecosystem is fubar
202  # linux builds should be built in the centos 5 vm for maximum compatibility
203  # see https://github.com/pypa/manylinux
204  # see also https://github.com/angr/angr-dev/blob/master/bdist.sh
205  sys.argv.insert(idx + 1, 'manylinux1_' + platform.machine())
206  else:
207  # https://www.python.org/dev/peps/pep-0425/
208  sys.argv.insert(idx + 1, name.replace('.', '_').replace('-', '_'))
209 
210 long_desc = '''
211 Capstone is a disassembly framework with the target of becoming the ultimate
212 disasm engine for binary analysis and reversing in the security community.
213 
214 Created by Nguyen Anh Quynh, then developed and maintained by a small community,
215 Capstone offers some unparalleled features:
216 
217 - Support multiple hardware architectures: ARM, ARM64 (ARMv8), Mips, PPC, Sparc,
218  SystemZ, XCore and X86 (including X86_64).
219 
220 - Having clean/simple/lightweight/intuitive architecture-neutral API.
221 
222 - Provide details on disassembled instruction (called "decomposer" by others).
223 
224 - Provide semantics of the disassembled instruction, such as list of implicit
225  registers read & written.
226 
227 - Implemented in pure C language, with lightweight wrappers for C++, C#, Go,
228  Java, NodeJS, Ocaml, Python, Ruby & Vala ready (available in main code,
229  or provided externally by the community).
230 
231 - Native support for all popular platforms: Windows, Mac OSX, iOS, Android,
232  Linux, *BSD, Solaris, etc.
233 
234 - Thread-safe by design.
235 
236 - Special support for embedding into firmware or OS kernel.
237 
238 - High performance & suitable for malware analysis (capable of handling various
239  X86 malware tricks).
240 
241 - Distributed under the open source BSD license.
242 
243 Further information is available at http://www.capstone-engine.org
244 
245 
246 [License]
247 
248 This project is released under the BSD license. If you redistribute the binary
249 or source code of Capstone, please attach file LICENSE.TXT with your products.
250 '''
251 
252 setup(
253  provides=['capstone'],
254  packages=['capstone'],
255  name='capstone',
256  version=VERSION,
257  author='Nguyen Anh Quynh',
258  author_email='aquynh@gmail.com',
259  description='Capstone disassembly engine',
260  long_description=long_desc,
261  long_description_content_type="text/markdown",
262  url='https://www.capstone-engine.org',
263  python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
264  classifiers=[
265  'Development Status :: 5 - Production/Stable',
266  'Intended Audience :: Developers',
267  'Topic :: Software Development :: Build Tools',
268  'License :: OSI Approved :: BSD License',
269  'Programming Language :: Python :: 2',
270  'Programming Language :: Python :: 2.7',
271  'Programming Language :: Python :: 3',
272  ],
273  requires=['ctypes'],
274  cmdclass=cmdclass,
275  zip_safe=True,
276  include_package_data=True,
277  is_pure=False,
278  package_data={
279  "capstone": ["lib/*", "include/capstone/*"],
280  }
281 )
size_t len
Definition: 6502dis.c:15
def run(self)
Definition: setup.py:162
def run(self)
Definition: setup.py:187
def run(self)
Definition: setup.py:155
static RzBuffer * build(RzEgg *egg)
Definition: egg_bind.c:144
Definition: setup.py:1
def copy_sources()
Definition: setup.py:76
def build_libraries()
Definition: setup.py:108
def dummy_src()
Definition: setup.py:176
def clean_bins()
Definition: setup.py:72
int replace(char *string, const char *token, const char *fmt,...)
Definition: tms320_dasm.c:325