Build Wheels Better #8
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 Better | |
| on: | |
| workflow_dispatch: | |
| release: | |
| types: [published] | |
| permissions: | |
| contents: write | |
| jobs: | |
| bump_version: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.x" | |
| - name: Bump version with post increment | |
| run: | | |
| # Extract current version from setup.py | |
| current_version=$(grep -Eo 'version="[^"]*' setup.py | cut -d'"' -f2) | |
| echo "Current version: $current_version" | |
| # Increment post-release number if exists, otherwise start with .post1 | |
| if [[ "$current_version" == *".post"* ]]; then | |
| base_version=$(echo $current_version | sed 's/\.post[0-9]*//') | |
| post_number=$(echo $current_version | grep -Eo 'post[0-9]+' | grep -Eo '[0-9]+') | |
| new_post_number=$((post_number + 1)) | |
| new_version="${base_version}.post${new_post_number}" | |
| else | |
| new_version="${current_version}.post1" | |
| fi | |
| echo "New version: $new_version" | |
| sed -i "s|version=\"[^\"]*\"|version=\"$new_version\"|" setup.py | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Commit and push version bump | |
| run: | | |
| git config --global user.name "GitHub Actions" | |
| git config --global user.email "actions@github.com" | |
| git commit -am "Bump version to $new_version" | |
| git push | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| build_wheels: | |
| runs-on: ${{ matrix.os }} | |
| needs: bump_version | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| python-version: ["3.9", "3.10", "3.11", "3.12"] | |
| include: | |
| - os: ubuntu-latest | |
| arch: aarch64 | |
| python-version: '3.9' | |
| - os: ubuntu-latest | |
| arch: aarch64 | |
| python-version: '3.10' | |
| - os: ubuntu-latest | |
| arch: aarch64 | |
| python-version: '3.11' | |
| - os: ubuntu-latest | |
| arch: aarch64 | |
| python-version: '3.12' | |
| - os: macos-latest | |
| arch: arm64 | |
| python-version: '3.9' | |
| - os: macos-latest | |
| arch: arm64 | |
| python-version: '3.10' | |
| - os: macos-latest | |
| arch: arm64 | |
| python-version: '3.11' | |
| - os: macos-latest | |
| arch: arm64 | |
| python-version: '3.12' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Upgrade pip, setuptools, and wheel | |
| run: python -m pip install --upgrade pip setuptools wheel | |
| shell: bash | |
| - name: Clean up previous builds (Unix) | |
| run: | | |
| rm -rf build dist *.egg-info class-sz/python/classy_sz.*so class-sz/python/classy_sz.*egg-info | |
| - name: Set CIBW_BUILD for the correct CPython version | |
| run: | | |
| if [ "${{ matrix.python-version }}" == "3.9" ]; then | |
| echo "CIBW_BUILD=cp39-*" >> $GITHUB_ENV | |
| elif [ "${{ matrix.python-version }}" == "3.10" ]; then | |
| echo "CIBW_BUILD=cp310-*" >> $GITHUB_ENV | |
| elif [ "${{ matrix.python-version }}" == "3.11" ]; then | |
| echo "CIBW_BUILD=cp311-*" >> $GITHUB_ENV | |
| elif [ "${{ matrix.python-version }}" == "3.12" ]; then | |
| echo "CIBW_BUILD=cp312-*" >> $GITHUB_ENV | |
| fi | |
| shell: bash | |
| - name: Install cibuildwheel | |
| run: python -m pip install cibuildwheel | |
| shell: bash | |
| - name: Clear pip cache | |
| run: pip cache purge | |
| shell: bash | |
| - name: Build wheels for Linux | |
| if: matrix.os == 'ubuntu-latest' | |
| env: | |
| CIBW_ENVIRONMENT: "LDFLAGS='-L/usr/lib/x86_64-linux-gnu' CFLAGS='-I/usr/include' LIBRARY_PATH='/usr/lib/x86_64-linux-gnu:$LIBRARY_PATH' C_INCLUDE_PATH='/usr/include:$C_INCLUDE_PATH' LD_LIBRARY_PATH='/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH'" | |
| CIBW_BUILD: ${{ env.CIBW_BUILD }} | |
| CIBW_SKIP: "cp27-* cp34-* cp35-* cp36-* cp37-* cp38-* pp* *-manylinux_i686 *musllinux*" | |
| CIBW_BEFORE_BUILD: | | |
| curl -O https://ftp.gnu.org/gnu/gsl/gsl-2.7.1.tar.gz | |
| tar -xzf gsl-2.7.1.tar.gz | |
| cd gsl-2.7.1 | |
| ./configure --prefix=/usr/local | |
| make | |
| make install | |
| cd .. | |
| curl -O http://www.fftw.org/fftw-3.3.10.tar.gz | |
| tar -xzf fftw-3.3.10.tar.gz | |
| cd fftw-3.3.10 | |
| ./configure --prefix=/usr/local --enable-shared | |
| make | |
| make install | |
| run: python -m cibuildwheel --output-dir wheelhouse | |
| - name: Install dependencies on macOS | |
| if: matrix.os == 'macos-latest' | |
| run: | | |
| brew install gsl fftw libomp | |
| chmod +x select_makefile.sh | |
| ./select_makefile.sh | |
| make clean | |
| if [ ! -f /opt/homebrew/opt/libomp/include/omp.h ]; then | |
| echo "omp.h not found" && exit 1 | |
| fi | |
| if [ ! -f /opt/homebrew/opt/gsl/include/gsl/gsl_integration.h ]; then | |
| echo "gsl_integration.h not found" && exit 1 | |
| fi | |
| if [ ! -f /opt/homebrew/opt/fftw/include/fftw3.h ]; then | |
| echo "fftw3.h not found" && exit 1 | |
| fi | |
| export LIBRARY_PATH=/opt/homebrew/opt/libomp/lib:$LIBRARY_PATH | |
| export C_INCLUDE_PATH=/opt/homebrew/opt/libomp/include:$C_INCLUDE_PATH | |
| export DYLD_LIBRARY_PATH=/opt/homebrew/opt/libomp/lib:$DYLD_LIBRARY_PATH | |
| working-directory: class-sz | |
| - name: Build wheels for macOS | |
| if: matrix.os == 'macos-latest' | |
| env: | |
| CIBW_BUILD: ${{ env.CIBW_BUILD }} | |
| CIBW_ARCHS: "arm64" | |
| CIBW_SKIP: "cp27-* cp34-* cp35-* cp36-* cp37-* cp38-* pp*" | |
| MACOSX_DEPLOYMENT_TARGET: "14.0" | |
| LDFLAGS: "-L/opt/homebrew/opt/libomp/lib -L/opt/homebrew/opt/gsl/lib -L/opt/homebrew/opt/fftw/lib" | |
| CPPFLAGS: "-I/opt/homebrew/opt/libomp/include -I/opt/homebrew/opt/gsl/include -I/opt/homebrew/opt/fftw/include" | |
| LIBRARY_PATH: "/opt/homebrew/opt/libomp/lib:/opt/homebrew/opt/gsl/lib:/opt/homebrew/opt/fftw/lib:$LIBRARY_PATH" | |
| C_INCLUDE_PATH: "/opt/homebrew/opt/libomp/include:/opt/homebrew/opt/gsl/include:/opt/homebrew/opt/fftw/include:$C_INCLUDE_PATH" | |
| DYLD_LIBRARY_PATH: "/opt/homebrew/opt/libomp/lib:/opt/homebrew/opt/gsl/lib:/opt/homebrew/opt/fftw/lib:$DYLD_LIBRARY_PATH" | |
| run: python -m cibuildwheel --output-dir wheelhouse | |
| - name: Install dependencies for source distribution | |
| run: python -m pip install build Cython numpy classy_szfast | |
| shell: bash | |
| - name: Build source distribution (sdist) | |
| run: python -m build --sdist --outdir dist | |
| shell: bash | |
| - name: Upload built distributions (wheels and sdist) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: wheels-and-sdist-${{ matrix.os }}-${{ matrix.python-version }} | |
| path: | | |
| wheelhouse/*.whl | |
| dist/*.tar.gz | |
| - name: Install the built wheel | |
| run: | | |
| python -m pip install wheelhouse/*.whl && echo "SUCCESS" > wheel_install_status.txt || { | |
| echo "ERROR: The wheel is not supported on this platform, but marking the step as complete." | |
| echo "FAIL" > wheel_install_status.txt | |
| exit 0 | |
| } | |
| shell: bash | |
| - name: Check import of classy_sz | |
| run: | | |
| if grep -q "SUCCESS" wheel_install_status.txt; then | |
| python -c "import classy_sz; print('classy_sz imported successfully')" | |
| else | |
| echo "Skipping classy_sz import check due to previous wheel installation failure." | |
| fi | |
| shell: bash | |
| publish_wheels: | |
| runs-on: ubuntu-latest | |
| needs: build_wheels | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| python-version: ["3.9", "3.10", "3.11", "3.12"] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download built wheels and sdist | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: wheels-and-sdist-${{ matrix.os }}-${{ matrix.python-version }} | |
| path: wheels-and-sdist-${{ matrix.os }}-${{ matrix.python-version }} | |
| - name: Install dependencies for uploading | |
| run: python -m pip install -U pip twine packaging | |
| - name: Upload distributions to PyPI | |
| run: | | |
| mkdir -p wheelhouse dist | |
| if [ -d "wheels-and-sdist-${{ matrix.os }}-${{ matrix.python-version }}/wheelhouse" ]; then | |
| mv wheels-and-sdist-${{ matrix.os }}-${{ matrix.python-version }}/wheelhouse/* wheelhouse/ | |
| fi | |
| if [ -d "wheels-and-sdist-${{ matrix.os }}-${{ matrix.python-version }}/dist" ]; then | |
| mv wheels-and-sdist-${{ matrix.os }}-${{ matrix.python-version }}/dist/* dist/ | |
| fi | |
| upload_files_in_dir() { | |
| local dir=$1 | |
| if [ -d "$dir" ] && [ "$(ls -A $dir)" ]; then | |
| echo "Uploading files in $dir..." | |
| for file in "$dir"/*; do | |
| if [ -f "$file" ]; then | |
| echo "Uploading $file..." | |
| if ! twine upload "$file"; then | |
| echo "WARNING: Failed to upload $file, skipping..." | |
| fi | |
| fi | |
| done | |
| else | |
| echo "No files to upload in $dir." | |
| fi | |
| } | |
| upload_files_in_dir wheelhouse | |
| upload_files_in_dir dist | |
| env: | |
| TWINE_USERNAME: "__token__" | |
| TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} |