Complete meson-python build system migration with CI fixes #274
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 Wheels | |
| on: | |
| push: | |
| branches: [ public, mesonify ] | |
| tags: | |
| - v* | |
| pull_request: | |
| branches: [ public, mesonify ] | |
| # Allows you to run this workflow manually from the Actions tab | |
| workflow_dispatch: | |
| jobs: | |
| build_wheels: | |
| name: Build wheels on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # macos-15-intel is x86_64, macos-14 is arm64 | |
| os: [ubuntu-latest, macos-15-intel, macos-14] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: 'recursive' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.x' | |
| - name: Install cibuildwheel | |
| run: python -m pip install cibuildwheel==2.21.1 | |
| - name: Determine architecture | |
| id: arch | |
| run: | | |
| if [ "$RUNNER_OS" == "Linux" ]; then | |
| echo "arch=x86_64" >> $GITHUB_OUTPUT | |
| elif [ "$RUNNER_OS" == "macOS" ]; then | |
| # macos-15-intel is x86_64, macos-14 is arm64 | |
| if [[ "${{ matrix.os }}" == "macos-14" ]]; then | |
| echo "arch=arm64" >> $GITHUB_OUTPUT | |
| else | |
| echo "arch=x86_64" >> $GITHUB_OUTPUT | |
| fi | |
| fi | |
| - name: Install build dependencies | |
| run: | | |
| if [ "$RUNNER_OS" == "Linux" ]; then | |
| sudo apt-get update | |
| sudo apt-get install -y gfortran ninja-build pkg-config libopenblas-dev liblapack-dev libnetcdf-dev libhdf5-dev | |
| elif [ "$RUNNER_OS" == "macOS" ]; then | |
| brew install gcc meson ninja openblas netcdf hdf5 | |
| # Link gfortran | |
| for gfortran_bin in /opt/homebrew/bin/gfortran-* /usr/local/bin/gfortran-*; do | |
| if [ -f "$gfortran_bin" ]; then | |
| sudo ln -sf "$gfortran_bin" /usr/local/bin/gfortran && break | |
| fi | |
| done | |
| fi | |
| pip install meson | |
| - name: Build wheels | |
| run: python -m cibuildwheel --output-dir wheelhouse quippy | |
| env: | |
| # Skip Python 2.7, 3.5, 3.6, 3.7, 3.8, PyPy, and musllinux (requires Python >=3.9) | |
| CIBW_SKIP: "cp27-* cp35-* cp36-* cp37-* cp38-* pp* *musllinux*" | |
| CIBW_BUILD_VERBOSITY: 3 | |
| # Use manylinux2014 for Linux | |
| CIBW_MANYLINUX_X86_64_IMAGE: "manylinux2014" | |
| # Install system dependencies in build containers | |
| CIBW_BEFORE_ALL_LINUX: > | |
| yum install -y openblas-devel lapack-devel netcdf-devel hdf5-devel | |
| CIBW_BEFORE_ALL_MACOS: > | |
| brew install openblas netcdf hdf5 || true | |
| # Build QUIP libraries inside each wheel's isolated environment | |
| # Install meson/ninja in the current Python environment, then build QUIP | |
| CIBW_BEFORE_BUILD_LINUX: > | |
| pip install meson ninja && | |
| cd {package} && cd .. && | |
| meson setup builddir && | |
| meson compile -C builddir | |
| CIBW_BEFORE_BUILD_MACOS: > | |
| pip install meson ninja && | |
| cd {package} && cd .. && | |
| PKG_CONFIG_PATH="/opt/homebrew/opt/openblas/lib/pkgconfig:/usr/local/opt/openblas/lib/pkgconfig" meson setup builddir && | |
| meson compile -C builddir | |
| # Set environment variables for builds | |
| # Linux: Set PKG_CONFIG_PATH to where openblas.pc is installed | |
| CIBW_ENVIRONMENT_LINUX: > | |
| PKG_CONFIG_PATH="/usr/lib64/pkgconfig:/usr/local/lib64/pkgconfig" | |
| # macOS: Add paths for openblas | |
| CIBW_ENVIRONMENT_MACOS: > | |
| PATH="/opt/homebrew/bin:/usr/local/bin:$PATH" | |
| PKG_CONFIG_PATH="/opt/homebrew/opt/openblas/lib/pkgconfig:/usr/local/opt/openblas/lib/pkgconfig" | |
| # macOS: Custom repair command to handle duplicate libgfortran libraries | |
| # delocate has issues with multiple libgfortran.dylib paths from QUIP's multiple libraries | |
| # Try repair with arch check, then without, then skip repair (copy wheel as-is) | |
| CIBW_REPAIR_WHEEL_COMMAND_MACOS: > | |
| delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} || | |
| delocate-wheel -w {dest_dir} -v {wheel} || | |
| cp {wheel} {dest_dir}/ | |
| # Build with meson-python (already configured in pyproject.toml) | |
| CIBW_BUILD_FRONTEND: "build" | |
| # Architecture setting | |
| CIBW_ARCHS: ${{ steps.arch.outputs.arch }} | |
| - name: Debug - list environment | |
| if: failure() | |
| run: | | |
| echo "=== Environment ===" | |
| env | sort | |
| echo "=== Python info ===" | |
| python --version | |
| pip list | |
| # Uncomment to get SSH access for testing | |
| # - name: Setup tmate session | |
| # if: failure() | |
| # uses: mxschmitt/action-tmate@v3 | |
| # timeout-minutes: 15 | |
| - name: Upload wheels as artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: wheels-${{ matrix.os }} | |
| path: ./wheelhouse/*.whl | |
| # Combine all wheels and create release | |
| release: | |
| name: Create release | |
| needs: build_wheels | |
| runs-on: ubuntu-latest | |
| if: startsWith(github.ref, 'refs/tags/') | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Download all wheel artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: wheels-* | |
| merge-multiple: true | |
| path: wheelhouse | |
| - name: Build source tarball | |
| run: | | |
| pip install git-archive-all | |
| version=$(echo ${{ github.ref }} | sed -e 's|refs/tags/||') | |
| git-archive-all QUIP-$version.tar.gz | |
| - name: Release wheels and source tarball | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| wheelhouse/*.whl | |
| QUIP-*.tar.gz | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Check if production release tag | |
| id: check-tag | |
| run: | | |
| if [[ ${{ github.ref }} =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "match=true" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Deploy to PyPI | |
| if: steps.check-tag.outputs.match == 'true' | |
| run: | | |
| pip install twine | |
| twine upload wheelhouse/*.whl | |
| env: | |
| TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} | |
| TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} |