Skip to content

Enable the SuiteSparse:GraphBLAS JIT #95

Enable the SuiteSparse:GraphBLAS JIT

Enable the SuiteSparse:GraphBLAS JIT #95

Workflow file for this run

name: Python wheel package build and publish
on:
release:
types: [published]
# Enable Run Workflow button in GitHub UI
workflow_dispatch:
inputs:
# Manual dispatch allows optional upload of wheels to PyPI
upload_dest:
type: choice
description: Upload wheels to
options:
- No Upload
- PyPI
- Test PyPI
push:
branches: [ main ]
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
# For PyPI Trusted Publisher
id-token: write
jobs:
build_sdist:
name: Build SDist
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build SDist
run: pipx run build --sdist
- name: Check metadata
run: pipx run twine check dist/*
- uses: actions/upload-artifact@v3
with:
path: dist/*.tar.gz
build_wheels:
name: Wheels - ${{ matrix.cibw_archs }} ${{ matrix.arch_note}} - ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
cibw_archs: "auto64"
# Linux x86 manylinux
- os: ubuntu-latest
cibw_archs: "x86_64"
# Python 3.12 wheel requires libffi-devel to be installed. manylinux container uses yum
cibw_before_build_linux: "yum install -y libffi-devel"
# skip musllinux
cibw_skip: "*musl*"
# Linux x86 musllinux
# Separate runner for a Musl build of graphblas. The glibc build is not guaranteed to be compatible.
- os: ubuntu-latest
cibw_archs: "x86_64"
arch_note: "musl"
# skip manylinux (built elsewhere), PyPy (no musl numpy wheels), CPython 3.8 (no musl numpy wheels)
cibw_skip: "*many* pp* cp38*"
# Linux aarch64
# Separate runner because this requires emulation (only x86 runners are available) and is very slow.
- os: ubuntu-latest
cibw_archs: "aarch64"
# numpy wheels not available for aarch64 PyPy or musllinux
cibw_skip: "pp* *musl*"
# macOS x86
- os: macos-latest
cibw_archs: "x86_64"
# macOS Apple Silicon cross-compiled on x86 macOS runner.
# GitHub does not offer Apple Silicon yet (only for self-hosted).
# See https://github.com/github/roadmap/issues/528
- os: macos-latest
cibw_archs: "arm64"
# Skip macOS ARM tests on Intel runner.
cibw_test_skip: "*-macosx_arm64"
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# aarch64 Linux builds are cross-compiled on x86 runners using emulation
# see https://cibuildwheel.readthedocs.io/en/stable/faq/#emulation
- name: Setup QEMU (for aarch64)
if: matrix.cibw_archs == 'aarch64'
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: Setup env (for aarch64)
if: matrix.cibw_archs == 'aarch64'
# Ask suitesparse.sh to compile faster by optimizing fewer types. Otherwise, the build takes too long to finish
# in 6 hour limit.
run: |
echo "SUITESPARSE_FAST_BUILD=1" >> $GITHUB_ENV
- name: Setup for testing
if: github.event_name == 'push' || github.event_name == 'pull_request'
# Ask suitesparse.sh to compile in the fastest way possible and provide a GB version to build
run: |
echo "SUITESPARSE_FASTEST_BUILD=1" >> $GITHUB_ENV
shell: bash
- name: Setup GraphBLAS version from GB_VERSION.txt
# Use GraphBLAS version specified in GB_VERSION.txt unless specified in a git tag (next workflow step).
# Git tag method required for uploads to PyPI.
if: github.event_name != 'release' && github.event.inputs.upload_dest != 'PyPI'
run: echo "GB_VERSION_REF=refs/tags/$(cat GB_VERSION.txt).0" >> $GITHUB_ENV
shell: bash
- name: Setup GraphBLAS version from git tag
if: ${{ startsWith(github.ref, 'refs/tags/') }}
# If this is a tagged ref, like a release, then use the tag for the graphblas version
run: echo "GB_VERSION_REF=${{ github.ref }}" >> $GITHUB_ENV
shell: bash
- name: Install tools (macOS)
if: contains(matrix.os, 'macos')
# Install coreutils which includes `nproc` used by `make -j` in suitesparse.sh
#
# GitHub actions comes with libomp already installed, but for its native arch only. Must build universal one
# manually so that both x86 and arm builds can be built.
run: |
brew fetch --retry coreutils && brew install coreutils
brew fetch --retry libomp && brew install libomp
if [[ ${{ matrix.cibw_archs }} == "arm64" ]] ; then
echo "Building universal libomp manually"
sh add_arm_to_libomp_dylib.sh || exit 1
fi
- uses: pypa/[email protected]
with:
output-dir: wheelhouse
env:
# very verbose
CIBW_BUILD_VERBOSITY: 3
# Build SuiteSparse
CIBW_BEFORE_ALL: bash suitesparse.sh ${{ env.GB_VERSION_REF }}
CIBW_BEFORE_BUILD_LINUX: ${{ matrix.cibw_before_build_linux }}
CIBW_ENVIRONMENT_PASS_LINUX: SUITESPARSE_FAST_BUILD SUITESPARSE_FASTEST_BUILD
# CMAKE_GNUtoMS=ON asks suitesparse.sh to build libraries in MSVC style on Windows.
CIBW_ENVIRONMENT_WINDOWS: CMAKE_GNUtoMS=ON GRAPHBLAS_PREFIX="C:/GraphBLAS"
# macOS libomp requires special configs. BREW_LIBOMP=1 asks suitesparse.sh to include them.
# SUITESPARSE_MACOS_ARCH asks to build a particular architecture. Either x86 or arm64.
CIBW_ENVIRONMENT_MACOS: BREW_LIBOMP="1" SUITESPARSE_MACOS_ARCH=${{ matrix.cibw_archs }}
# Uncomment to only build CPython wheels
# CIBW_BUILD: "cp*"
# Architectures to build specified in matrix
CIBW_ARCHS: ${{ matrix.cibw_archs }}
# as of writing numpy does not support pypy 3.10
CIBW_SKIP: "${{ matrix.cibw_skip }} pp310*"
# Use delvewheel on Windows.
# This copies graphblas.dll into the wheel. "repair" in cibuildwheel parlance includes copying any shared
# libraries from the build host into the wheel to make the wheel self-contained.
# Cibuildwheel includes tools for this for Linux and macOS, and they recommend delvewheel for Windows.
# Note: Currently using a workaround: --no-mangle instead of stripping graphblas.dll
# see https://github.com/adang1345/delvewheel/issues/33
CIBW_BEFORE_BUILD_WINDOWS: "pip install delvewheel"
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --add-path \"C:\\GraphBLAS\\bin\" --no-mangle \"libgomp-1.dll;libgcc_s_seh-1.dll\" -w {dest_dir} {wheel}"
# make cibuildwheel install test dependencies from pyproject.toml
CIBW_TEST_EXTRAS: "test"
# run tests
CIBW_TEST_COMMAND: "pytest --pyargs suitesparse_graphblas -s -k test_print_jit_config && pytest -v --pyargs suitesparse_graphblas"
CIBW_TEST_SKIP: ${{ matrix.cibw_test_skip }}
- uses: actions/upload-artifact@v3
id: uploadAttempt1
continue-on-error: true
with:
path: wheelhouse/*.whl
if-no-files-found: error
# Retry upload if first attempt failed. This happens somewhat randomly and for irregular reasons.
# Logic is a duplicate of previous step.
- uses: actions/upload-artifact@v3
id: uploadAttempt2
if: steps.uploadAttempt1.outcome == 'failure'
continue-on-error: false
with:
path: wheelhouse/*.whl
if-no-files-found: error
upload_all:
name: Upload to PyPI
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
# only upload releases to PyPI
if: github.repository == 'GraphBLAS/python-suitesparse-graphblas' && ((github.event_name == 'release' && github.event.action == 'published') || (github.event_name == 'workflow_dispatch' && github.event.inputs.upload_dest != 'No Upload'))
steps:
- uses: actions/setup-python@v5
with:
python-version: "3.x"
- uses: actions/download-artifact@v3
with:
name: artifact
path: dist
# Upload to PyPI
- uses: pypa/gh-action-pypi-publish@release/v1
name: Upload to PyPI
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.upload_dest == 'PyPI')
with:
# PyPI does not allow replacing a file. Without this flag the entire action fails if even a single duplicate exists.
skip-existing: true
verbose: true
password: ${{ secrets.PYPI_TOKEN }}
# Upload to Test PyPI
- uses: pypa/gh-action-pypi-publish@release/v1
name: Upload to Test PyPI
if: github.event_name == 'workflow_dispatch' && github.event.inputs.upload_dest == 'Test PyPI'
with:
# PyPI does not allow replacing a file. Without this flag the entire action fails if even a single duplicate exists.
skip-existing: true
verbose: true
repository-url: https://test.pypi.org/legacy/