Skip to content

Fix macOS wheel bundling by setting DYLD_LIBRARY_PATH for delocate #285

Fix macOS wheel bundling by setting DYLD_LIBRARY_PATH for delocate

Fix macOS wheel bundling by setting DYLD_LIBRARY_PATH for delocate #285

Workflow file for this run

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: Set version from git tag
if: startsWith(github.ref, 'refs/tags/v')
run: |
VERSION="${GITHUB_REF#refs/tags/v}"
echo "Setting version to $VERSION from tag"
echo "$VERSION" > quippy/VERSION
# Update meson.build version (meson-python reads from project() call)
# Only update the project version line, not meson_version
sed -i.bak "s/^ version: '[^']*'/ version: '$VERSION'/" quippy/meson.build
rm -f quippy/meson.build.bak
echo "Updated quippy/meson.build:"
head -5 quippy/meson.build
- 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: 1
# 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 and LD_LIBRARY_PATH for auditwheel to find QUIP libraries
CIBW_ENVIRONMENT_LINUX: >
PKG_CONFIG_PATH="/usr/lib64/pkgconfig:/usr/local/lib64/pkgconfig"
LD_LIBRARY_PATH="/project/builddir/src/libAtoms:/project/builddir/src/fox:/project/builddir/src/GAP:/project/builddir/src/Potentials:/project/builddir/src/Utils:$LD_LIBRARY_PATH"
# macOS: Pass through GITHUB_WORKSPACE and set library paths
CIBW_ENVIRONMENT_PASS_MACOS: "GITHUB_WORKSPACE"
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"
QUIP_LIB_PATH="${GITHUB_WORKSPACE}/builddir/src/libAtoms:${GITHUB_WORKSPACE}/builddir/src/fox:${GITHUB_WORKSPACE}/builddir/src/GAP:${GITHUB_WORKSPACE}/builddir/src/Potentials:${GITHUB_WORKSPACE}/builddir/src/Utils"
# macOS: Custom repair command to bundle QUIP libraries into wheel
# DYLD_LIBRARY_PATH helps delocate find QUIP shared libraries
CIBW_REPAIR_WHEEL_COMMAND_MACOS: >
DYLD_LIBRARY_PATH="${QUIP_LIB_PATH}"
delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}
# 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 }}