Skip to content

Commit 870f1d5

Browse files
authored
Merge pull request #2 from pnnl/release-0.1.1
Implement PyPI publishing with multi-platform wheel building and prebuilt dependencies
2 parents a483cc4 + ef05d72 commit 870f1d5

23 files changed

Lines changed: 1336 additions & 674 deletions
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: Build Dependency Binaries
2+
3+
on:
4+
# Disabled - kept for reference only
5+
# workflow_dispatch:
6+
# workflow_call:
7+
8+
env:
9+
GMP_VERSION: "6.3.0"
10+
MPFR_VERSION: "4.2.2"
11+
12+
jobs:
13+
build-prebuilts:
14+
name: Build GMP & MPFR (${{ matrix.artifact_suffix }})
15+
runs-on: ${{ matrix.os }}
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
include:
20+
- os: ubuntu-latest
21+
artifact_suffix: linux-x86_64
22+
- os: ubuntu-22.04-arm
23+
artifact_suffix: linux-arm64
24+
- os: macos-14
25+
artifact_suffix: macos-arm64
26+
- os: macos-13
27+
artifact_suffix: macos-x86_64
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
32+
- name: Install build dependencies (Linux)
33+
if: runner.os == 'Linux'
34+
run: |
35+
sudo apt-get update
36+
sudo apt-get install -y build-essential autoconf automake libtool m4 texinfo pkg-config
37+
38+
- name: Install build dependencies (macOS)
39+
if: runner.os == 'macOS'
40+
run: |
41+
brew update
42+
brew install automake libtool m4 pkg-config
43+
44+
45+
- name: Build GMP and MPFR
46+
shell: bash
47+
env:
48+
ARTIFACT_SUFFIX: ${{ matrix.artifact_suffix }}
49+
run: |
50+
set -euxo pipefail
51+
52+
JOBS=1
53+
if command -v nproc >/dev/null 2>&1; then
54+
JOBS=$(nproc)
55+
elif command -v sysctl >/dev/null 2>&1; then
56+
JOBS=$(sysctl -n hw.logicalcpu)
57+
fi
58+
59+
ROOT_DIR="${PWD}/prebuilt"
60+
INSTALL_PREFIX="${ROOT_DIR}/install"
61+
SRC_DIR="${ROOT_DIR}/src"
62+
ARTIFACT_DIR="${ROOT_DIR}/artifacts"
63+
mkdir -p "${INSTALL_PREFIX}" "${SRC_DIR}" "${ARTIFACT_DIR}"
64+
65+
cd "${SRC_DIR}"
66+
67+
THIRD_PARTY_DIR="${GITHUB_WORKSPACE}/third_party"
68+
GMP_ARCHIVE="${THIRD_PARTY_DIR}/gmp-${GMP_VERSION}.tar.xz"
69+
MPFR_ARCHIVE="${THIRD_PARTY_DIR}/mpfr-${MPFR_VERSION}.tar.xz"
70+
71+
if [ ! -f "${GMP_ARCHIVE}" ]; then
72+
echo "Missing GMP archive at ${GMP_ARCHIVE}" >&2
73+
exit 1
74+
fi
75+
76+
if [ ! -f "${MPFR_ARCHIVE}" ]; then
77+
echo "Missing MPFR archive at ${MPFR_ARCHIVE}" >&2
78+
exit 1
79+
fi
80+
81+
COMMON_CFLAGS="-O2 -fPIC"
82+
COMMON_CXXFLAGS="-O2 -fPIC"
83+
84+
tar -xf "${GMP_ARCHIVE}"
85+
cd "gmp-${GMP_VERSION}"
86+
CPPFLAGS="${CPPFLAGS:-}" CFLAGS="${COMMON_CFLAGS}" CXXFLAGS="${COMMON_CXXFLAGS}" ./configure --prefix="${INSTALL_PREFIX}" --enable-static --disable-shared --with-pic
87+
make CFLAGS="${COMMON_CFLAGS}" CXXFLAGS="${COMMON_CXXFLAGS}" -j"${JOBS}"
88+
make CFLAGS="${COMMON_CFLAGS}" CXXFLAGS="${COMMON_CXXFLAGS}" install
89+
cd ..
90+
91+
tar -xf "${MPFR_ARCHIVE}"
92+
cd "mpfr-${MPFR_VERSION}"
93+
export CPPFLAGS="-I${INSTALL_PREFIX}/include ${CPPFLAGS:-}"
94+
export LDFLAGS="-L${INSTALL_PREFIX}/lib ${LDFLAGS:-}"
95+
CFLAGS="${COMMON_CFLAGS}" CXXFLAGS="${COMMON_CXXFLAGS}" ./configure --prefix="${INSTALL_PREFIX}" --with-gmp="${INSTALL_PREFIX}" --enable-static --disable-shared --with-pic
96+
make CFLAGS="${COMMON_CFLAGS}" CXXFLAGS="${COMMON_CXXFLAGS}" -j"${JOBS}"
97+
make CFLAGS="${COMMON_CFLAGS}" CXXFLAGS="${COMMON_CXXFLAGS}" install
98+
cd ..
99+
100+
BUNDLE_NAME="gmp-${GMP_VERSION}_mpfr-${MPFR_VERSION}_${ARTIFACT_SUFFIX}"
101+
tar -C "${INSTALL_PREFIX}" -czf "${ARTIFACT_DIR}/${BUNDLE_NAME}.tar.gz" .
102+
103+
104+
- name: Upload artifact
105+
uses: actions/upload-artifact@v4
106+
with:
107+
name: gmp-mpfr-${{ matrix.artifact_suffix }}
108+
path: prebuilt/artifacts
109+
if-no-files-found: error
110+
retention-days: 7
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
name: Build and Install (Multi-Platform)
2+
3+
on:
4+
# Disabled - kept for reference only
5+
# workflow_dispatch:
6+
# workflow_call:
7+
8+
env:
9+
CMAKE_BUILD_PARALLEL_LEVEL: 4
10+
11+
jobs:
12+
compile-and-install:
13+
name: ${{ matrix.name }}
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
include:
19+
- name: Linux x86_64
20+
os: ubuntu-22.04
21+
python-version: '3.11'
22+
- name: Linux ARM64
23+
os: ubuntu-22.04-arm
24+
python-version: '3.11'
25+
- name: macOS x86_64
26+
os: macos-13
27+
python-version: '3.11'
28+
- name: macOS arm64
29+
os: macos-14
30+
python-version: '3.11'
31+
32+
steps:
33+
- name: Checkout
34+
uses: actions/checkout@v4
35+
36+
- name: Install dependencies (Linux)
37+
if: runner.os == 'Linux'
38+
run: |
39+
sudo apt-get update
40+
sudo apt-get install -y build-essential ninja-build python3-dev libssl-dev
41+
42+
- name: Install dependencies (macOS)
43+
if: runner.os == 'macOS'
44+
run: |
45+
brew update
46+
brew install ninja
47+
48+
49+
50+
- name: Set up Python
51+
uses: actions/setup-python@v5
52+
with:
53+
python-version: ${{ matrix.python-version }}
54+
55+
- name: Upgrade pip and wheel
56+
run: |
57+
python -m pip install --upgrade pip wheel
58+
59+
- name: Install build frontends
60+
run: |
61+
python -m pip install scikit-build-core pybind11 pytest
62+
63+
64+
- name: Configure CMake
65+
run: |
66+
cmake -S . -B build-cli \
67+
-G Ninja \
68+
-DCMAKE_BUILD_TYPE=Release \
69+
-DNWQEC_BUILD_PYTHON=OFF
70+
71+
- name: Build CLI
72+
run: |
73+
cmake --build build-cli --parallel
74+
75+
- name: Smoke test CLI
76+
run: |
77+
./build-cli/nwqec-cli tests/python/fixtures/fixture_circuit.qasm -o build-cli/fixture_circuit_ct.qasm
78+
test -f build-cli/fixture_circuit_ct.qasm
79+
./build-cli/gridsynth pi/8 12
80+
81+
82+
83+
84+
- name: Pip install project
85+
run: |
86+
python -m pip install .
87+
88+
- name: Verify Python package import
89+
run: |
90+
python -c "import nwqec; print('nwqec version:', nwqec.__version__); print('WITH_GRIDSYNTH_CPP:', nwqec.WITH_GRIDSYNTH_CPP)"
91+
92+
- name: Run Python tests
93+
run: |
94+
python -m pytest tests/python

.github/workflows/build-wheels.yml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: Build Wheels
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
tags:
8+
- 'v*' # Trigger on version tags
9+
pull_request:
10+
branches:
11+
- main
12+
workflow_dispatch: # Allow manual triggering
13+
14+
jobs:
15+
build-wheels:
16+
name: Build wheels on ${{ matrix.os }}
17+
runs-on: ${{ matrix.os }}
18+
strategy:
19+
matrix:
20+
# Build on multiple platforms
21+
include:
22+
- os: ubuntu-latest
23+
cibw_archs: "x86_64"
24+
- os: ubuntu-22.04-arm
25+
cibw_archs: "aarch64"
26+
- os: macos-15-intel
27+
cibw_archs: "x86_64"
28+
- os: macos-latest
29+
cibw_archs: "arm64"
30+
31+
steps:
32+
- name: Checkout code
33+
uses: actions/checkout@v4
34+
35+
- name: Set up Python
36+
uses: actions/setup-python@v5
37+
with:
38+
python-version: '3.12'
39+
40+
- name: Install cibuildwheel
41+
run: python -m pip install cibuildwheel
42+
43+
- name: Build wheels
44+
run: python -m cibuildwheel --output-dir wheelhouse
45+
env:
46+
CIBW_ARCHS: ${{ matrix.cibw_archs }}
47+
48+
- name: Upload wheels as artifacts
49+
uses: actions/upload-artifact@v4
50+
with:
51+
name: wheels-${{ matrix.os }}-${{ matrix.cibw_archs }}-${{ github.run_id }}
52+
path: ./wheelhouse/*.whl
53+
retention-days: 30
54+
55+
build-sdist:
56+
name: Build source distribution
57+
runs-on: ubuntu-latest
58+
steps:
59+
- name: Checkout code
60+
uses: actions/checkout@v4
61+
62+
- name: Set up Python
63+
uses: actions/setup-python@v5
64+
with:
65+
python-version: '3.12'
66+
67+
- name: Install build
68+
run: python -m pip install build
69+
70+
- name: Build sdist
71+
run: python -m build --sdist
72+
73+
- name: Upload sdist as artifact
74+
uses: actions/upload-artifact@v4
75+
with:
76+
name: sdist-${{ github.run_id }}
77+
path: ./dist/*.tar.gz
78+
retention-days: 30
79+
80+
# Optional: Upload to PyPI on tagged releases
81+
upload-pypi:
82+
name: Upload to PyPI
83+
needs: [build-wheels, build-sdist]
84+
runs-on: ubuntu-latest
85+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
86+
environment:
87+
name: pypi
88+
url: https://pypi.org/p/nwqec
89+
permissions:
90+
id-token: write # For trusted publishing
91+
92+
steps:
93+
- name: Download all artifacts
94+
uses: actions/download-artifact@v4
95+
with:
96+
pattern: "*-${{ github.run_id }}"
97+
merge-multiple: true
98+
path: dist/
99+
100+
- name: Publish to PyPI
101+
uses: pypa/gh-action-pypi-publish@release/v1

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
# Ignore build directories
1313
/build/
14+
build-*/
1415
/debug/
1516
/release/
1617

0 commit comments

Comments
 (0)