Build Wheels for Sequenzo #151
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
| # GitHub Actions workflow for Sequenzo package | |
| name: Build Wheels for Sequenzo | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| pull_request: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| jobs: | |
| build: | |
| name: Build ${{ matrix.os }} Py${{ matrix.python-version }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| python-version: ['3.9', '3.10', '3.11', '3.12'] | |
| steps: | |
| - name: Checkout source with submodules | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Set up Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Ensure setuptools/wheel for macOS Python 3.12 | |
| if: runner.os == 'macOS' && matrix.python-version == '3.12' | |
| run: python -m pip install --upgrade pip setuptools wheel | |
| # Add OpenMP support | |
| - name: Install OpenMP (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| brew install libomp | |
| echo "CC=clang" >> $GITHUB_ENV | |
| echo "CXX=clang++" >> $GITHUB_ENV | |
| echo "LDFLAGS=-L$(brew --prefix libomp)/lib" >> $GITHUB_ENV | |
| echo "CPPFLAGS=-I$(brew --prefix libomp)/include" >> $GITHUB_ENV | |
| echo "SEQUENZO_ENABLE_OPENMP=1" >> $GITHUB_ENV | |
| - name: Install OpenMP (Linux) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libomp-dev | |
| echo "SEQUENZO_ENABLE_OPENMP=1" >> $GITHUB_ENV | |
| - name: Setup MSVC with OpenMP (Windows) | |
| if: runner.os == 'Windows' | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| with: | |
| arch: x64 | |
| - name: Enable OpenMP (Windows) | |
| if: runner.os == 'Windows' | |
| run: | | |
| echo "SEQUENZO_ENABLE_OPENMP=1" >> $env:GITHUB_ENV | |
| - name: Install R (Windows) | |
| if: runner.os == 'Windows' | |
| uses: r-lib/actions/setup-r@v2 | |
| with: | |
| r-version: '4.3.1' | |
| # Install dependencies with fallback strategy | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install --only-binary=all "numpy<2.5" || pip install "numpy<2.5" | |
| pip install --only-binary=all "scipy<1.16" || echo "scipy will be installed in cibuildwheel" | |
| pip install --prefer-binary Cython pybind11 build "cibuildwheel==2.23.3" twine | |
| pip install --prefer-binary fastcluster || echo "fastcluster installation attempted" | |
| - name: Build Cython wheels on macOS | |
| if: runner.os == 'macOS' | |
| run: | | |
| python setup.py build_ext --inplace | |
| python -m build | |
| - name: Clean previous build outputs | |
| if: runner.os != 'macOS' | |
| run: | | |
| rm -rf build/ dist/ *.egg-info | |
| find . -name "*.so" -delete | |
| shell: bash | |
| - name: Build wheels with cibuildwheel | |
| if: runner.os != 'macOS' | |
| run: python -m cibuildwheel --output-dir dist | |
| env: | |
| CIBW_SKIP: "*-musllinux* pp*" # 跳过 musllinux 和 PyPy | |
| CIBW_ARCHS_WINDOWS: "AMD64" | |
| CIBW_ARCHS_LINUX: "x86_64" | |
| CIBW_BUILD_VERBOSITY: "1" | |
| # Environment variables | |
| CIBW_ENVIRONMENT_LINUX: SEQUENZO_ENABLE_OPENMP=1 | |
| CIBW_ENVIRONMENT_WINDOWS: SEQUENZO_ENABLE_OPENMP=1 DISTUTILS_USE_SDK=1 | |
| # Linux: install system dependencies | |
| CIBW_BEFORE_BUILD_LINUX: | | |
| sudo apt-get update | |
| sudo apt-get install -y libomp-dev r-base r-base-dev | |
| python -m pip install --upgrade pip | |
| python -m pip install rpy2 | |
| echo "System dependencies installation attempted" | |
| # Windows: skip all extra dependencies, let setup.py handle them | |
| CIBW_BEFORE_BUILD_WINDOWS: | | |
| echo "Using setup.py dependencies only" | |
| REM --- 临时从 PATH 移除 Rtools bin --- | |
| set PATH=%PATH:C:\rtools43\usr\bin;=% | |
| REM --- 确保 MSVC link.exe 在 PATH 前面 --- | |
| set PATH=C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64;%PATH% | |
| python -m pip install --upgrade pip | |
| python -m pip install rpy2 | |
| # Universal dependency installation (fallback) | |
| CIBW_BEFORE_BUILD: > | |
| echo "Using setup.py dependencies only" | |
| # Test command | |
| CIBW_TEST_COMMAND: > | |
| python -c "import sequenzo; print('Sequenzo import successful'); | |
| import importlib; | |
| mod = importlib.util.find_spec('sequenzo.clustering.clustering_c_code'); | |
| print('C++ extensions loaded' if mod else 'WARNING: C++ extensions not found')" | |
| - name: Show dist content | |
| run: ls -lah dist/ | |
| shell: bash | |
| - name: Check wheels | |
| run: twine check dist/* | |
| - name: Verify OpenMP Support | |
| run: | | |
| echo "=== Verifying built wheels ===" | |
| python -c " | |
| import subprocess | |
| import sys | |
| import os | |
| wheel_files = [f for f in os.listdir('dist') if f.endswith('.whl') and 'cp${{ matrix.python-version }}' in f.replace('.', '')] | |
| if wheel_files: | |
| wheel_file = wheel_files[0] | |
| print(f'Installing wheel: {wheel_file}') | |
| subprocess.run([sys.executable, '-m', 'pip', 'install', '--force-reinstall', f'dist/{wheel_file}'], check=True) | |
| import sequenzo | |
| print('Sequenzo import successful') | |
| try: | |
| import sequenzo.clustering.clustering_c_code as cc | |
| print('C++ extensions loaded successfully') | |
| except ImportError as e: | |
| print(f'WARNING: C++ extensions loading failed: {e}') | |
| else: | |
| print('ERROR: No matching wheel files found') | |
| " | |
| shell: bash | |
| - name: Upload wheels | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: wheels-${{ matrix.os }}-${{ matrix.python-version }} | |
| path: dist/ |