Add ARM wheels build in CI #15
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build ARM Wheels for Paddle | |
| on: | |
| push: | |
| branches: [paddle] | |
| tags: ["v*"] | |
| pull_request: | |
| merge_group: | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref_name }}-${{ github.ref_type == 'branch' && github.sha }}-${{ github.event_name == 'workflow_dispatch' }} | |
| cancel-in-progress: true | |
| permissions: | |
| id-token: write | |
| contents: write | |
| defaults: | |
| run: | |
| shell: bash -l -eo pipefail {0} | |
| env: | |
| PADDLECODEC_TEST_VIDEO_URL: https://paddlenlp.bj.bcebos.com/datasets/paddlemix/demo_video/example_video.mp4 | |
| PADDLECODEC_TEST_VIDEO_CACHE_KEY: paddlecodec-test-video-v1-example-video | |
| PADDLECODEC_TEST_VIDEO_PATH: .github/test-assets/example_video.mp4 | |
| jobs: | |
| generate-matrix: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| build-matrix: ${{ steps.set-matrix.outputs.build-matrix }} | |
| test-matrix: ${{ steps.set-matrix.outputs.test-matrix }} | |
| steps: | |
| - name: Generate ARM build and test matrix | |
| id: set-matrix | |
| run: | | |
| python - <<'PY' | |
| import itertools | |
| import json | |
| import os | |
| python_versions = ["3.9", "3.10", "3.11", "3.12", "3.13"] | |
| # FFmpeg 8.0 is intentionally excluded for Paddle CPU builds to match | |
| # the existing x86 workflow and avoid the current OpenVINO conflict. | |
| ffmpeg_versions = ["4.4.2", "5.1.2", "6.1.1", "7.0.1"] | |
| build_matrix = {"python-version": python_versions} | |
| test_matrix = { | |
| "include": [ | |
| { | |
| "python-version": python_version, | |
| "ffmpeg-version": ffmpeg_version, | |
| } | |
| for python_version, ffmpeg_version in itertools.product( | |
| python_versions, ffmpeg_versions | |
| ) | |
| ] | |
| } | |
| with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as f: | |
| f.write(f"build-matrix={json.dumps(build_matrix)}\n") | |
| f.write(f"test-matrix={json.dumps(test_matrix)}\n") | |
| PY | |
| prepare-test-video: | |
| runs-on: ubuntu-latest | |
| name: Prepare cached Paddle test video | |
| steps: | |
| - name: Restore cached test video | |
| id: cache-test-video | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ env.PADDLECODEC_TEST_VIDEO_PATH }} | |
| key: ${{ env.PADDLECODEC_TEST_VIDEO_CACHE_KEY }} | |
| - name: Download test video | |
| if: steps.cache-test-video.outputs.cache-hit != 'true' | |
| run: | | |
| mkdir -p "$(dirname "${PADDLECODEC_TEST_VIDEO_PATH}")" | |
| curl --fail --location --retry 5 --retry-all-errors \ | |
| --output "${PADDLECODEC_TEST_VIDEO_PATH}" \ | |
| "${PADDLECODEC_TEST_VIDEO_URL}" | |
| - name: Upload cached test video artifact | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: paddlecodec-test-video | |
| path: ${{ env.PADDLECODEC_TEST_VIDEO_PATH }} | |
| if-no-files-found: error | |
| build: | |
| needs: generate-matrix | |
| name: Build and Upload ARM wheel | |
| runs-on: ubuntu-24.04-arm | |
| container: | |
| image: pytorch/manylinux2_28_aarch64-builder:cpu-aarch64 | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJson(needs.generate-matrix.outputs.build-matrix) }} | |
| permissions: | |
| id-token: write | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup conda environment | |
| uses: conda-incubator/setup-miniconda@v3 | |
| with: | |
| auto-update-conda: true | |
| miniforge-version: latest | |
| activate-environment: build | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install build dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install build wheel setuptools | |
| - name: Install PaddlePaddle nightly | |
| run: | | |
| pip install --pre paddlepaddle -i https://www.paddlepaddle.org.cn/packages/nightly/cpu/ | |
| - name: Run pre-build script | |
| run: | | |
| bash packaging/pre_build_script.sh | |
| - name: Build wheel | |
| run: | | |
| # Match upstream's Linux workflow and build the ARM wheel against the | |
| # pre-built non-GPL FFmpeg bundles published on S3. | |
| export BUILD_AGAINST_ALL_FFMPEG_FROM_S3=1 | |
| export I_CONFIRM_THIS_IS_NOT_A_LICENSE_VIOLATION=1 | |
| export TORCHCODEC_CMAKE_BUILD_DIR=$(pwd)/build_cmake | |
| python -m build --wheel -vvv --no-isolation | |
| - name: Repair wheel | |
| run: | | |
| pip install auditwheel | |
| # 1. Extract internal libraries from the wheel to a temporary directory | |
| # This allows auditwheel to find them when checking dependencies | |
| mkdir -p temp_libs | |
| unzip -j dist/*.whl "torchcodec/*.so" -d temp_libs || true | |
| # 2. Prepare LD_LIBRARY_PATH | |
| # FFmpeg libraries fetched from the build-time S3 bundles | |
| FFMPEG_LIB_PATHS=$(find "$(pwd)/build_cmake/_deps" -type d -name "lib" -print | paste -sd: -) | |
| # PaddlePaddle libraries | |
| PADDLE_PATH=$(python -c "import paddle; print(paddle.__path__[0])") | |
| PADDLE_LIB_PATHS="$PADDLE_PATH/base:$PADDLE_PATH/libs" | |
| # Wheel internal libraries | |
| INTERNAL_LIB_PATH=$(pwd)/temp_libs | |
| export LD_LIBRARY_PATH=${FFMPEG_LIB_PATHS}:${PADDLE_LIB_PATHS}:${INTERNAL_LIB_PATH}:${LD_LIBRARY_PATH} | |
| # 3. Repair wheel with auditwheel | |
| # We exclude all external libraries because we want to rely on system libraries (like FFmpeg) | |
| # or libraries provided by other packages (like PaddlePaddle). | |
| # auditwheel 6.1.0+ supports wildcards in --exclude. | |
| auditwheel repair dist/*.whl --plat manylinux_2_28_aarch64 -w wheelhouse/ --exclude "*" | |
| # Cleanup | |
| rm -rf temp_libs | |
| rm dist/*.whl | |
| mv wheelhouse/*.whl dist/ | |
| rmdir wheelhouse | |
| - name: Upload wheel artifact | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: paddlecodec-wheel-linux-arm64-py${{ matrix.python-version }} | |
| path: dist/*.whl | |
| - name: Run post-build script | |
| run: | | |
| bash packaging/post_build_script.sh | |
| - name: List wheel contents | |
| run: | | |
| wheel_path=$(find dist -type f -name "*.whl") | |
| echo "Wheel path: $wheel_path" | |
| unzip -l $wheel_path | |
| install-and-test: | |
| needs: [generate-matrix, prepare-test-video, build] | |
| name: Install and test ARM wheel | |
| runs-on: ubuntu-24.04-arm | |
| container: | |
| image: pytorch/manylinux2_28_aarch64-builder:cpu-aarch64 | |
| env: | |
| PADDLECODEC_TEST_VIDEO: .github/test-assets/example_video.mp4 | |
| strategy: | |
| fail-fast: false | |
| # Match the existing Paddle x86 flow while keeping the upstream-style staged | |
| # build/test split: exercise every Python and FFmpeg combination post-build. | |
| matrix: ${{ fromJson(needs.generate-matrix.outputs.test-matrix) }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Download wheel artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: paddlecodec-wheel-linux-arm64-py${{ matrix.python-version }} | |
| path: dist/ | |
| - name: Download cached test video artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: paddlecodec-test-video | |
| path: .github/test-assets/ | |
| - name: Install FFmpeg via conda | |
| uses: conda-incubator/setup-miniconda@v3 | |
| with: | |
| auto-update-conda: true | |
| miniforge-version: latest | |
| activate-environment: test | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install FFmpeg from conda-forge | |
| run: | | |
| conda install "ffmpeg=${{ matrix.ffmpeg-version }}" -c conda-forge -y | |
| ffmpeg -version | |
| - name: Install PaddlePaddle nightly in conda env | |
| run: | | |
| pip install --pre paddlepaddle -i https://www.paddlepaddle.org.cn/packages/nightly/cpu/ | |
| - name: Install paddlecodec from wheel | |
| run: | | |
| wheel_path=$(find dist -type f -name "*.whl") | |
| echo "Installing $wheel_path" | |
| pip install $wheel_path -vvv | |
| - name: Install test dependencies | |
| run: | | |
| pip install numpy pytest pillow | |
| - name: Delete src folder | |
| run: | | |
| # Delete src/ to ensure we're testing the installed wheel, not source code | |
| rm -rf src/ | |
| ls -la | |
| - name: Run tests | |
| run: | | |
| pytest --override-ini="addopts=-v" -s test_paddle | |
| publish-pypi-arm: | |
| runs-on: ubuntu-latest | |
| name: Publish ARM Wheels to PyPI | |
| if: "startsWith(github.ref, 'refs/tags/')" | |
| needs: | |
| - install-and-test | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Retrieve ARM release distributions | |
| uses: actions/download-artifact@v6 | |
| with: | |
| pattern: paddlecodec-wheel-linux-arm64-* | |
| path: dist/ | |
| merge-multiple: true | |
| - name: Publish ARM release distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| publish-release-arm: | |
| runs-on: ubuntu-latest | |
| name: Publish ARM Wheels to GitHub | |
| if: "startsWith(github.ref, 'refs/tags/')" | |
| needs: | |
| - install-and-test | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| pattern: paddlecodec-wheel-linux-arm64-* | |
| path: dist/ | |
| merge-multiple: true | |
| - name: Publish ARM wheels to GitHub | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| draft: true | |
| files: dist/* | |
| tag_name: ${{ github.ref_name }} |