diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 00000000..028c193e --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,60 @@ +name: PyPI 📦 Distribution + +on: [push] + +jobs: + deploy: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-latest, macos-latest, ubuntu-latest] + platform: [x32, x64] + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Set up MSVC + if: matrix.os == 'windows-latest' + uses: microsoft/setup-msbuild@v1 + + - name: Install dependencies + run: | + pip install setuptools wheel + + - name: Build distribution 📦 + shell: bash + run: | + if [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'windows-latest' ]; then + cd bindings/python && python setup.py build -p win32 sdist bdist_wheel -p win32 + rm dist/*.tar.gz + elif [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'ubuntu-latest' ]; then + docker run --rm -v `pwd`/:/work dockcross/manylinux1-x86 > ./dockcross + chmod +x ./dockcross + ./dockcross bindings/python/build_wheel.sh + elif [ ${{ matrix.platform }} == 'x64' ] && [ ${{ matrix.os }} == 'ubuntu-latest' ]; then + docker run --rm -v `pwd`/:/work dockcross/manylinux1-x64 > ./dockcross + chmod +x ./dockcross + ./dockcross bindings/python/build_wheel.sh + elif [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'macos-latest' ]; then + cd bindings/python && python setup.py sdist + else + cd bindings/python && python setup.py bdist_wheel + fi + + - uses: actions/upload-artifact@v2 + with: + name: unicorn-packages-${{ matrix.os }}-${{ matrix.platform }} + path: ${{ github.workspace }}/bindings/python/dist/* + + - name: Publish distribution 📦 to PyPI + if: startsWith(github.event.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@master + with: + username: __token__ + password: ${{ secrets.pypi_pass }} + packages_dir: ${{ github.workspace }}/bindings/python/dist/ diff --git a/bindings/python/build_wheel.sh b/bindings/python/build_wheel.sh new file mode 100755 index 00000000..e3c9d444 --- /dev/null +++ b/bindings/python/build_wheel.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e -x + +cd bindings/python + +# Compile wheels +if [ -f /opt/python/cp36-cp36m/bin/python ];then + /opt/python/cp36-cp36m/bin/python setup.py bdist_wheel +else + python3 setup.py bdist_wheel +fi +cd dist +auditwheel repair *.whl +mv -f wheelhouse/*.whl . diff --git a/bindings/python/setup.py b/bindings/python/setup.py index 98b94ad2..d261c7c7 100755 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -15,6 +15,7 @@ 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 +from setuptools.command.develop import develop SYSTEM = sys.platform @@ -22,7 +23,7 @@ SYSTEM = sys.platform IS_64BITS = platform.architecture()[0] == '64bit' # are we building from the repository or from a source distribution? -ROOT_DIR = os.path.dirname(os.path.realpath(__file__)) +ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) LIBS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'lib') HEADERS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'include') SRC_DIR = os.path.join(ROOT_DIR, 'src') @@ -140,16 +141,22 @@ def build_libraries(): os.chdir(BUILD_DIR) try: - subprocess.check_call(['msbuild', '/help']) + subprocess.check_call(['msbuild', '-ver']) except: has_msbuild = False else: has_msbuild = True if has_msbuild and SYSTEM == 'win32': - plat = 'Win32' if platform.architecture()[0] == '32bit' else 'x64' + if platform.architecture()[0] == '32bit': + plat = 'Win32' + elif 'win32' in sys.argv: + plat = 'Win32' + else: + plat = 'x64' + conf = 'Debug' if os.getenv('DEBUG', '') else 'Release' - subprocess.call(['msbuild', '-m', '-p:Platform=' + plat, '-p:Configuration=' + conf], cwd=os.path.join(BUILD_DIR, 'msvc')) + subprocess.call(['msbuild', 'unicorn.sln', '-m', '-p:Platform=' + plat, '-p:Configuration=' + conf], cwd=os.path.join(BUILD_DIR, 'msvc')) obj_dir = os.path.join(BUILD_DIR, 'msvc', plat, conf) shutil.copy(os.path.join(obj_dir, LIBRARY_FILE), LIBS_DIR) @@ -191,7 +198,6 @@ def build_libraries(): sys.exit(1) os.chdir(cwd) - class custom_sdist(sdist): def run(self): clean_bins() @@ -207,6 +213,12 @@ class custom_build(build): build_libraries() return build.run(self) +class custom_develop(develop): + def run(self): + log.info("Building C extensions") + build_libraries() + return develop.run(self) + class custom_bdist_egg(bdist_egg): def run(self): self.run_command('build') @@ -215,10 +227,6 @@ class custom_bdist_egg(bdist_egg): def dummy_src(): return [] -cmdclass = {} -cmdclass['build'] = custom_build -cmdclass['sdist'] = custom_sdist -cmdclass['bdist_egg'] = custom_bdist_egg if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv: idx = sys.argv.index('bdist_wheel') + 1 @@ -239,24 +247,10 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv: # https://www.python.org/dev/peps/pep-0425/ sys.argv.insert(idx + 1, name.replace('.', '_').replace('-', '_')) -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.") - -def join_all(src, files): - return tuple(os.path.join(src, f) for f in files) long_desc = ''' Unicorn is a lightweight, multi-platform, multi-architecture CPU emulator framework -based on [QEMU](http://qemu.org). +based on [QEMU](https://qemu.org). Unicorn offers some unparalleled features: @@ -269,7 +263,7 @@ Unicorn offers some unparalleled features: - Thread-safety by design - Distributed under free software license GPLv2 -Further information is available at http://www.unicorn-engine.org +Further information is available at https://www.unicorn-engine.org ''' setup( @@ -282,17 +276,17 @@ setup( description='Unicorn CPU emulator engine', long_description=long_desc, long_description_content_type="text/markdown", - url='http://www.unicorn-engine.org', + url='https://www.unicorn-engine.org', classifiers=[ 'License :: OSI Approved :: BSD License', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', ], requires=['ctypes'], - cmdclass=cmdclass, + cmdclass={'build': custom_build, 'develop': custom_develop, 'sdist': custom_sdist, 'bdist_egg': custom_bdist_egg}, zip_safe=True, include_package_data=True, - is_pure=True, + is_pure=False, package_data={ 'unicorn': ['lib/*', 'include/unicorn/*'] }