From 3ecd46aa0e70df7dd78f720a2660d6da211c4a51 Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Thu, 5 Oct 2023 00:20:37 -0700 Subject: [PATCH] Add wheel CI for PR and update release (#376) --- .github/workflows/release.yml | 79 ++++++++++-------- .github/workflows/wheels.yml | 70 ++++++++++++++++ MANIFEST.in | 2 +- setup.py | 10 ++- .../attach_process/attach_linux_amd64.so | Bin 22760 -> 31424 bytes 5 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 .github/workflows/wheels.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 93a84925..6cab971e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,52 +5,28 @@ on: types: [created] jobs: - deploy-wheels: - name: Deploy wheels on ${{ matrix.os }} for ${{ matrix.arch }} + deploy-wheels-linux: + name: Deploy wheels on Linux for ${{ matrix.arch }} runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest] python-version: [38, 39, 310, 311, 312] - manylinux-image: [manylinux2014, manylinux_2_24] - arch: [auto] - include: - - os: ubuntu-latest - manylinux-image: manylinux2014 - arch: aarch64 - python-version: 38 - - os: ubuntu-latest - manylinux-image: manylinux2014 - arch: aarch64 - python-version: 39 - - os: ubuntu-latest - manylinux-image: manylinux2014 - arch: aarch64 - python-version: 310 - - os: ubuntu-latest - manylinux-image: manylinux2014 - arch: aarch64 - python-version: 311 - - os: ubuntu-latest - manylinux-image: manylinux2014 - arch: aarch64 - python-version: 312 - exclude: - # manyliunx image is not a valid variation on MacOS and Windows - - os: macos-latest - manylinux-image: manylinux2014 - - os: windows-latest - manylinux-image: manylinux2014 + manylinux-image: [manylinux2014] + arch: [auto, aarch64] steps: - uses: actions/checkout@v3 + - name: Set up QEMU if: ${{ matrix.arch == 'aarch64' }} uses: docker/setup-qemu-action@v1 + - name: Set up Python uses: actions/setup-python@v4 with: python-version: 3.9 + - name: Install dependencies run: | python -m pip install --upgrade pip @@ -64,10 +40,47 @@ jobs: env: CIBW_BUILD: 'cp${{ matrix.python-version }}-*' CIBW_SKIP: '*musllinux*' - CIBW_ARCHS: ${{matrix.arch}} + CIBW_ARCHS: ${{ matrix.arch }} CIBW_MANYLINUX_*_IMAGE: ${{ matrix.manylinux-image }} CIBW_MANYLINUX_I686_IMAGE: ${{ matrix.manylinux-image }} + - name: Publish wheels to PyPI Unix + continue-on-error: true + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + twine upload wheelhouse/*.whl + + deploy-wheels-macos-windows: + name: Deploy wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, windows-latest] + python-version: [38, 39, 310, 311, 312] + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build twine flake8 setuptools wheel + + - name: Install cibuildwheel + run: python -m pip install cibuildwheel -U + + - name: Build wheels + run: python -m cibuildwheel --output-dir wheelhouse + env: + CIBW_BUILD: 'cp${{ matrix.python-version }}-*' + - name: Publish wheels to PyPI Unix if: matrix.os != 'windows-latest' continue-on-error: true diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml new file mode 100644 index 00000000..bcb471df --- /dev/null +++ b/.github/workflows/wheels.yml @@ -0,0 +1,70 @@ +name: wheels + +on: + push: + branches: [ master ] + pull_request: + +jobs: + build-wheels-linux: + name: Build wheels on Linux for ${{ matrix.arch }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + python-version: [38, 39, 310, 311, 312] + manylinux-image: [manylinux2014] + arch: [auto, aarch64] + + steps: + - uses: actions/checkout@v3 + - name: Set up QEMU + if: ${{ matrix.arch == 'aarch64' }} + uses: docker/setup-qemu-action@v1 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build twine flake8 setuptools wheel + + - name: Install cibuildwheel + run: python -m pip install cibuildwheel -U + + - name: Build wheels + run: python -m cibuildwheel --output-dir wheelhouse + env: + CIBW_BUILD: 'cp${{ matrix.python-version }}-*' + CIBW_SKIP: '*musllinux*' + CIBW_ARCHS: ${{ matrix.arch }} + CIBW_MANYLINUX_*_IMAGE: ${{ matrix.manylinux-image }} + CIBW_MANYLINUX_I686_IMAGE: ${{ matrix.manylinux-image }} + + build-wheels-macos-windows: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, windows-latest] + python-version: [38, 39, 310, 311, 312] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build twine flake8 setuptools wheel + + - name: Install cibuildwheel + run: python -m pip install cibuildwheel -U + + - name: Build wheels + run: python -m cibuildwheel --output-dir wheelhouse + env: + CIBW_BUILD: 'cp${{ matrix.python-version }}-*' diff --git a/MANIFEST.in b/MANIFEST.in index a8d58476..53526611 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,4 +6,4 @@ include setup.py recursive-include src/viztracer/html *.css *.js recursive-include src/viztracer/modules *.c *.h recursive-include src/viztracer/web_dist * -recursive-include src/viztracer/attach_process * +recursive-include src/viztracer/attach_process *.py diff --git a/setup.py b/setup.py index 0919f78d..9b118dee 100644 --- a/setup.py +++ b/setup.py @@ -18,10 +18,18 @@ ], } +if sys.platform == "win32": + package_data["viztracer"].extend([ + "attach_process/attach_x86.dll", + "attach_process/attach_x86_64.dll", + "attach_process/inject_dll.exe", + "attach_process/inject_dll_amd64.exe", + "attach_process/run_code_on_dllmain_amd64.dll", + "attach_process/run_code_on_dllmain_x86.dll", + ]) if sys.platform == "darwin": package_data["viztracer"].extend([ "attach_process/attach_x86_64.dylib", - "attach_process/linux_and_mac/lldb_prepare.py", ]) elif sys.platform in ("linux", "linux2"): if platform.machine() == "i686": diff --git a/src/viztracer/attach_process/attach_linux_amd64.so b/src/viztracer/attach_process/attach_linux_amd64.so index 2aa799329ed9788bda61bf96fcdf1a7c6eae0054..30464f232528bd67afce00a23c1673ed343b2d2f 100755 GIT binary patch literal 31424 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

Hyi_tisJyHnU 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