# Multi-Platform Wheel Building for gconcord

This document explains the multi-platform wheel building setup for the gconcord package.

## Overview

The gconcord package uses GitHub Actions and cibuildwheel to automatically build wheels for multiple platforms:

- **Linux**: x86_64
- **macOS**: x86_64 (Intel) and arm64 (Apple Silicon)
- **Python versions**: 3.8, 3.9, 3.10, 3.11, 3.12

## Key Components

### 1. GitHub Actions Workflow

The workflow file `.github/workflows/build_wheels_multiplatform.yml` defines the build matrix:

- Builds wheels on Linux and macOS
- Tests wheels after building
- Uploads to PyPI on release

### 2. cibuildwheel Configuration

In `pyproject.toml`:

```toml
[tool.cibuildwheel]
build = ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*"]
skip = ["*-win32", "*-musllinux_*", "*-manylinux_i686", "*-win_amd64"]

[tool.cibuildwheel.macos]
archs = ["x86_64", "arm64"]
environment = { MACOSX_DEPLOYMENT_TARGET = "10.14" }

[tool.cibuildwheel.linux]
archs = ["x86_64"]
manylinux-x86_64-image = "manylinux2014"
```

### 3. Eigen Dependency Management

The package bundles Eigen headers to ensure consistent builds across platforms:

1. `scripts/download_eigen.py` downloads Eigen headers
2. `MANIFEST.in` includes Eigen in source distributions
3. `setup.py` prioritizes bundled Eigen over system installations

## Build Process

### Local Development

To test wheel building locally:

```bash
# Install cibuildwheel
pip install cibuildwheel

# Run the test script
python scripts/test_wheel_build.py

# Or build directly
python scripts/download_eigen.py .
cibuildwheel --platform auto
```

### CI/CD Pipeline

1. **On push/PR**: Builds and tests wheels
2. **On release**: Builds, tests, and uploads to PyPI

### Platform-Specific Notes

#### Linux
- Uses manylinux2014 for compatibility
- Requires OpenMP for multi-threading

#### macOS
- Minimum deployment target: macOS 10.14
- Universal2 wheels not built (separate x86_64 and arm64)
- Both Intel and Apple Silicon supported

## Wheel Compatibility Matrix

| Platform | Architecture | Python Versions | Wheel Tag Example |
|----------|-------------|-----------------|-------------------|
| Linux | x86_64 | 3.8-3.12 | cp311-cp311-manylinux2014_x86_64 |
| macOS | x86_64 | 3.8-3.12 | cp311-cp311-macosx_10_14_x86_64 |
| macOS | arm64 | 3.8-3.12 | cp311-cp311-macosx_11_0_arm64 |

## Troubleshooting

### Build Failures

1. **Eigen not found**: Ensure `scripts/download_eigen.py` runs successfully
2. **OpenMP errors on Linux**: The manylinux images include OpenMP
3. **Architecture mismatch**: Check CIBW_ARCHS environment variable

### Testing

Wheels are tested during the build process with:
- Import test: `import gconcord`
- pytest suite: `python -m pytest tests -v`

Tests are skipped on macOS ARM64 due to lack of native runners.

## Publishing

The workflow automatically publishes to PyPI when:
1. A GitHub release is created
2. The release is published (not draft)
3. All tests pass

Required setup:
- PyPI API token stored as `PYPI_API_TOKEN` secret
- Or use trusted publishing (OIDC) with proper permissions

## Future Improvements

1. Add Windows support (currently excluded)
2. Build universal2 wheels for macOS
3. Add more Python versions as they're released
4. Consider using newer manylinux standards (manylinux_2_28)