Skip to content

Build wheels

Build wheels #97

Workflow file for this run

name: Build wheels
on:
workflow_dispatch:
release:
types: [published]
permissions: # Ensure the workflow has permission to push changes
contents: write # Allow write access for pushing to the repository
jobs:
bump_version:
runs-on: ubuntu-latest
steps:
- name: Checkout the 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
current_version=$(grep -Eo 'version="[^"]*' setup.py | cut -d'"' -f2)
echo "Current version: $current_version"
# Check if it has a post-release (e.g., .post1)
if [[ "$current_version" == *".post"* ]]; then
# Increment post-release number
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
# First post release if there's no post number yet
new_version="${current_version}.post1"
fi
echo "New version: $new_version"
ls -alh
# Use bump2version with --current-version flag
# bump2version --current-version "$current_version" --new-version "$new_version" patch setup.py
# Update version in setup.py using sed
# sed -i '' "s/version=\"$current_version\"/version=\"$new_version\"/" setup.py
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 "[email protected]"
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'
# # Specific inclusion for Windows x86 architecture
# - os: windows-latest
# arch: amd64
# python-version: '3.9'
# - os: windows-latest
# arch: amd64
# python-version: '3.10'
steps:
- name: Checkout the code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
# Clean up on Unix-like systems
- name: Clean up previous builds (Unix)
if: runner.os != 'Windows'
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
fi
shell: bash
# - name: Install system dependencies (Linux)
# if: matrix.os == 'ubuntu-latest'
# run: |
# sudo apt-get install -y libgsl-dev libfftw3-dev
# echo "Include paths for GSL and FFTW:"
# dpkg -L libgsl-dev | grep '/include'
# dpkg -L libfftw3-dev | grep '/include'
# echo "Library paths for GSL and FFTW:"
# dpkg -L libgsl-dev | grep '/lib'
# dpkg -L libfftw3-dev | grep '/lib'
- name: Install cibuildwheel
run: python -m pip install cibuildwheel
shell: bash
# Build wheels for Linux (with custom build options)
- 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: "cp39-manylinux_x86_64" # Constrain build to cp39-manylinux_x86_64
CIBW_BUILD: ${{ env.CIBW_BUILD }}
CIBW_SKIP: "cp27-* cp34-* cp35-* cp36-* cp37-* cp38-* pp* *-manylinux_i686 *musllinux*"
CIBW_BEFORE_BUILD: |
# Build GSL from source
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
# Go back to the root directory to build FFTW
cd ..
# Build FFTW from source
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
# Print to check the files are correctly installed
# echo "Contents of /usr/local/include/gsl:"
# ls -la /usr/local/include/gsl/
# echo "Contents of /usr/local/include:"
# ls -la /usr/local/include/
# echo "Contents of /usr/local/lib:"
# ls -la /usr/local/lib/
run: |
# # Check GSL library and include files
# if [ -f /usr/lib/x86_64-linux-gnu/libgsl.so ]; then
# echo "GSL library found in /usr/lib/x86_64-linux-gnu/"
# else
# echo "GSL library not found in /usr/lib/x86_64-linux-gnu/"; exit 1;
# fi
# if [ -f /usr/include/gsl/gsl_sf_bessel.h ]; then
# echo "GSL include files found in /usr/include/gsl/"
# else
# echo "GSL include files not found in /usr/include/gsl/"; exit 1;
# fi
# # Check FFTW library and include files
# if [ -f /usr/lib/x86_64-linux-gnu/libfftw3.so ]; then
# echo "FFTW library found in /usr/lib/x86_64-linux-gnu/"
# else
# echo "FFTW library not found in /usr/lib/x86_64-linux-gnu/"; exit 1;
# fi
# if [ -f /usr/include/fftw3.h ]; then
# echo "FFTW include files found in /usr/include/"
# else
# echo "FFTW include files not found in /usr/include/"; exit 1;
# fi
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
# Check that omp.h is available in the include directory
if [ -f /opt/homebrew/opt/libomp/include/omp.h ]; then
echo "omp.h found"
else
echo "omp.h not found" && exit 1
fi
# Check that gsl_integration.h and fftw3.h are available
if [ -f /opt/homebrew/opt/gsl/include/gsl/gsl_integration.h ]; then
echo "gsl_integration.h found"
else
echo "gsl_integration.h not found" && exit 1
fi
if [ -f /opt/homebrew/opt/fftw/include/fftw3.h ]; then
echo "fftw3.h found"
else
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 # (Mac M1 users only)
working-directory: class-sz
# Build wheels for macOS (with Apple Silicon support)
- name: Build wheels for macOS
if: matrix.os == 'macos-latest'
env:
# CIBW_BUILD: "cp39-macosx_arm64" # Restrict to cp39-macosx_arm64
CIBW_BUILD: ${{ env.CIBW_BUILD }}
CIBW_ARCHS: "arm64"
CIBW_SKIP: "cp27-* cp34-* cp35-* cp36-* cp37-* cp38-* pp*"
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
# Build wheels for Windows using bash
- name: Build wheels for Windows
if: matrix.os == 'windows-latest'
env:
CIBW_BUILD: ${{ env.CIBW_BUILD }}
CIBW_SKIP: "cp27-* cp34-* cp35-* cp36-* cp37-* cp38-* pp* *-win32"
# CIBW_ARCHS: "x86" # Force cibuildwheel to use x86 only
LIBRARY_PATH: "$(pwd)/fftw/lib;$(pwd)/gsl/lib"
C_INCLUDE_PATH: "$(pwd)/fftw/include;$(pwd)/gsl/include"
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
shell: bash
- 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
# - name: Run pytests if classy_sz is installed
# run: |
# if grep -q "SUCCESS" wheel_install_status.txt; then
# pytest --maxfail=1 --disable-warnings
# else
# echo "Skipping pytest 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 the 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
- name: Upload distributions to PyPI
run: |
ls
ls -R wheels-and-sdist-${{ matrix.os }}-${{ matrix.python-version }}
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
local filetype=$2 # This could be "wheelhouse" or "dist"
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 and continuing..."
fi
fi
done
else
echo "No $filetype files to upload."
fi
}
# Upload wheel files
upload_files_in_dir wheelhouse "wheel"
# Upload source distribution files
upload_files_in_dir dist "source distribution"
env:
TWINE_USERNAME: "__token__"
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}