| #!/usr/bin/env python |
| |
| import glob |
| import os |
| import shutil |
| import sys |
| import platform |
| |
| from distutils import log |
| from setuptools import setup |
| from distutils.util import get_platform |
| from distutils.command.build import build |
| from distutils.command.sdist import sdist |
| from setuptools.command.bdist_egg import bdist_egg |
| |
| SYSTEM = sys.platform |
| |
| # 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, 'capstone', 'lib') |
| HEADERS_DIR = os.path.join(ROOT_DIR, 'capstone', '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, '../..') |
| |
| # Parse version from pkgconfig.mk |
| VERSION_DATA = {} |
| with open(os.path.join(BUILD_DIR, 'pkgconfig.mk')) as fp: |
| lines = fp.readlines() |
| for line in lines: |
| line = line.strip() |
| if len(line) == 0: |
| continue |
| if line.startswith('#'): |
| continue |
| if '=' not in line: |
| continue |
| |
| k, v = line.split('=', 1) |
| k = k.strip() |
| v = v.strip() |
| if len(k) == 0 or len(v) == 0: |
| continue |
| VERSION_DATA[k] = v |
| |
| if 'PKG_MAJOR' not in VERSION_DATA or \ |
| 'PKG_MINOR' not in VERSION_DATA or \ |
| 'PKG_EXTRA' not in VERSION_DATA: |
| raise Exception("Malformed pkgconfig.mk") |
| |
| if 'PKG_TAG' in VERSION_DATA: |
| VERSION = '{PKG_MAJOR}.{PKG_MINOR}.{PKG_EXTRA}.{PKG_TAG}'.format(**VERSION_DATA) |
| else: |
| VERSION = '{PKG_MAJOR}.{PKG_MINOR}.{PKG_EXTRA}'.format(**VERSION_DATA) |
| |
| if SYSTEM == 'darwin': |
| VERSIONED_LIBRARY_FILE = "libcapstone.{PKG_MAJOR}.dylib".format(**VERSION_DATA) |
| 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.{PKG_MAJOR}".format(**VERSION_DATA) |
| LIBRARY_FILE = "libcapstone.so" |
| STATIC_LIBRARY_FILE = 'libcapstone.a' |
| |
| def clean_bins(): |
| shutil.rmtree(LIBS_DIR, ignore_errors=True) |
| shutil.rmtree(HEADERS_DIR, ignore_errors=True) |
| |
| def copy_sources(): |
| """Copy the C sources into the source directory. |
| This rearranges the source files under the python distribution |
| directory. |
| """ |
| src = [] |
| |
| try: |
| shutil.rmtree("src/") |
| except (IOError, OSError): |
| pass |
| |
| shutil.copytree(os.path.join(BUILD_DIR, "arch"), os.path.join(SRC_DIR, "arch")) |
| shutil.copytree(os.path.join(BUILD_DIR, "include"), os.path.join(SRC_DIR, "include")) |
| |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "*.[ch]"))) |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "*.mk"))) |
| |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "Makefile"))) |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "LICENSE*"))) |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "README"))) |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "*.TXT"))) |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "RELEASE_NOTES"))) |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "make.sh"))) |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "CMakeLists.txt"))) |
| src.extend(glob.glob(os.path.join(BUILD_DIR, "pkgconfig.mk"))) |
| |
| for filename in src: |
| outpath = os.path.join(SRC_DIR, os.path.basename(filename)) |
| log.info("%s -> %s" % (filename, outpath)) |
| shutil.copy(filename, outpath) |
| |
| 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')) |
| |
| # if prebuilt libraries are available, use those and cancel build |
| if os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE)) and \ |
| (not STATIC_LIBRARY_FILE or os.path.exists(os.path.join(ROOT_DIR, 'prebuilt', STATIC_LIBRARY_FILE))): |
| shutil.copy(os.path.join(ROOT_DIR, 'prebuilt', LIBRARY_FILE), LIBS_DIR) |
| if STATIC_LIBRARY_FILE is not None: |
| shutil.copy(os.path.join(ROOT_DIR, 'prebuilt', STATIC_LIBRARY_FILE), LIBS_DIR) |
| return |
| |
| 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") |
| elif "bsd" in SYSTEM: |
| # *BSD distinguishes make (BSD) vs gmake (GNU). Use cmake + bsd make :-) |
| 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 ..') |
| os.system("make") |
| 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)) |
| |
| # only copy static library if it exists (it's a build option) |
| if STATIC_LIBRARY_FILE and os.path.exists(STATIC_LIBRARY_FILE): |
| shutil.copy(STATIC_LIBRARY_FILE, LIBS_DIR) |
| os.chdir(cwd) |
| |
| |
| class custom_sdist(sdist): |
| def run(self): |
| clean_bins() |
| copy_sources() |
| return sdist.run(self) |
| |
| |
| class custom_build(build): |
| def run(self): |
| if 'LIBCAPSTONE_PATH' in os.environ: |
| log.info('Skipping building C extensions since LIBCAPSTONE_PATH is set') |
| else: |
| log.info('Building C extensions') |
| build_libraries() |
| return build.run(self) |
| |
| |
| class custom_bdist_egg(bdist_egg): |
| def run(self): |
| self.run_command('build') |
| return bdist_egg.run(self) |
| |
| def dummy_src(): |
| return [] |
| |
| cmdclass = {} |
| cmdclass['build'] = custom_build |
| cmdclass['sdist'] = custom_sdist |
| cmdclass['bdist_egg'] = custom_bdist_egg |
| |
| try: |
| from setuptools.command.develop import develop |
| class custom_develop(develop): |
| def run(self): |
| log.info("Building C extensions") |
| build_libraries() |
| return develop.run(self) |
| |
| cmdclass['develop'] = custom_develop |
| except ImportError: |
| print("Proper 'develop' support unavailable.") |
| |
| 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 6 vm for maximum compatibility |
| # see https://github.com/pypa/manylinux |
| # see also https://github.com/angr/angr-dev/blob/master/bdist.sh and |
| # https://www.python.org/dev/peps/pep-0599/ |
| sys.argv.insert(idx + 1, 'manylinux2014_' + platform.machine()) |
| else: |
| # https://www.python.org/dev/peps/pep-0425/ |
| sys.argv.insert(idx + 1, name.replace('.', '_').replace('-', '_')) |
| |
| long_desc = ''' |
| Capstone is a disassembly framework with the target of becoming the ultimate |
| disasm engine for binary analysis and reversing in the security community. |
| |
| Created by Nguyen Anh Quynh, then developed and maintained by a small community, |
| Capstone offers some unparalleled features: |
| |
| - Support multiple hardware architectures: ARM, ARM64 (ARMv8), Mips, PPC, Sparc, |
| SystemZ, XCore and X86 (including X86_64). |
| |
| - Having clean/simple/lightweight/intuitive architecture-neutral API. |
| |
| - Provide details on disassembled instruction (called "decomposer" by others). |
| |
| - Provide semantics of the disassembled instruction, such as list of implicit |
| registers read & written. |
| |
| - Implemented in pure C language, with lightweight wrappers for C++, C#, Go, |
| Java, NodeJS, Ocaml, Python, Ruby & Vala ready (available in main code, |
| or provided externally by the community). |
| |
| - Native support for all popular platforms: Windows, Mac OSX, iOS, Android, |
| Linux, *BSD, Solaris, etc. |
| |
| - Thread-safe by design. |
| |
| - Special support for embedding into firmware or OS kernel. |
| |
| - High performance & suitable for malware analysis (capable of handling various |
| X86 malware tricks). |
| |
| - Distributed under the open source BSD license. |
| |
| Further information is available at http://www.capstone-engine.org |
| |
| |
| [License] |
| |
| This project is released under the BSD license. If you redistribute the binary |
| or source code of Capstone, please attach file LICENSE.TXT with your products. |
| ''' |
| |
| setup( |
| provides=['capstone'], |
| packages=['capstone'], |
| name='capstone', |
| version=VERSION, |
| author='Nguyen Anh Quynh', |
| author_email='aquynh@gmail.com', |
| description='Capstone disassembly engine', |
| long_description=long_desc, |
| long_description_content_type="text/markdown", |
| url='https://www.capstone-engine.org', |
| python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', |
| classifiers=[ |
| 'Development Status :: 5 - Production/Stable', |
| 'Intended Audience :: Developers', |
| 'Topic :: Software Development :: Build Tools', |
| 'License :: OSI Approved :: BSD License', |
| 'Programming Language :: Python :: 2', |
| 'Programming Language :: Python :: 2.7', |
| 'Programming Language :: Python :: 3', |
| ], |
| requires=['ctypes'], |
| cmdclass=cmdclass, |
| zip_safe=True, |
| include_package_data=True, |
| is_pure=False, |
| package_data={ |
| "capstone": ["lib/*", "include/capstone/*"], |
| } |
| ) |