66 - " v*"
77 workflow_dispatch :
88
9- # ---- Centralized version pins for Linux path ----
10- env :
11- # Tooling
12- CCACHE_VER : " 4.11.3" # Linux tarballs (x86_64/aarch64)
13- CIBW_VER : " v3.0.1" # cibuildwheel tag
14- PYTHON_VER : " 3.12" # runner Python to drive builds
15-
16- # Native deps (Linux build)
17- FFTW_VER : " 3.3.10"
18- BOOST_VER_U : " 1_89_0" # underscored for URL
19- BOOST_VER_D : " 1.89.0" # dotted for path
20-
219jobs :
2210 sdist :
2311 name : Build sdist
2412 runs-on : ubuntu-latest
2513 permissions :
2614 contents : read
2715 steps :
28- - uses : actions/checkout@v5
16+ - uses : actions/checkout@v4
2917 with :
3018 fetch-depth : 0
3119
32- - uses : actions/setup-python@v6
20+ - uses : actions/setup-python@v5
3321 with :
34- python-version : ${{ env.PYTHON_VER }}
22+ python-version : " 3.12 "
3523
3624 - name : Build source distribution
3725 run : |
@@ -44,48 +32,112 @@ jobs:
4432 name : dist-sdist
4533 path : dist/*
4634
47-
35+ # ----- Linux x86_64 (native) -----
4836 wheels-linux-x86_64 :
4937 name : Build Linux wheels (x86_64)
5038 runs-on : ubuntu-latest
51- permissions : { contents: read }
39+ permissions :
40+ contents : read
5241 steps :
53- - uses : actions/checkout@v5
54- with : { fetch-depth: 0 }
42+ - uses : actions/checkout@v4
43+ with :
44+ fetch-depth : 0
5545
56- - name : Build wheels with cibuildwheel
57- uses : pypa/cibuildwheel@${{ env.CIBW_VER }}
46+ # Cache compiled objects across ABIs & runs
47+ - name : Restore ccache
48+ uses : actions/cache@v4
49+ with :
50+ path : .ccache
51+ key : ccache-linux-x86_64-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake', '**/*.cpp', '**/*.h', 'pyproject.toml') }}
52+
53+ # Cache third-party source tarballs so BEFORE_ALL can just extract
54+ - name : Restore 3rdparty source cache
55+ uses : actions/cache@v4
56+ with :
57+ path : build-cache
58+ key : thirdparty-src-x86_64-fftw-3.3.10-boost-1_84_0
59+
60+ - name : Pre-fetch Boost/FFTW (host)
61+ run : |
62+ set -eux
63+ mkdir -p build-cache
64+ # FFTW
65+ test -f build-cache/fftw-3.3.10.tar.gz || \
66+ curl -fsSL -o build-cache/fftw-3.3.10.tar.gz http://www.fftw.org/fftw-3.3.10.tar.gz
67+ # Boost headers
68+ test -f build-cache/boost_1_84_0.tar.gz || \
69+ curl -fsSL -o build-cache/boost_1_84_0.tar.gz https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.gz
70+
71+ - name : Build wheels with cibuildwheel (x86_64)
72+ uses : pypa/cibuildwheel@v2.21.3
5873 env :
59- CIBW_BUILD : cp310-manylinux_x86_64 cp311-manylinux_x86_64 cp312-manylinux_x86_64
74+ CIBW_BUILD : cp310-* cp311-* cp312-*
75+ CIBW_SKIP : pp* *-musllinux_*
6076 CIBW_ARCHS_LINUX : x86_64
6177 CIBW_MANYLINUX_X86_64_IMAGE : manylinux_2_28
62-
63- # ---- same pinned prebuilds as before ----
6478 CIBW_BEFORE_ALL_LINUX : |
6579 set -eux
66- if command -v yum >/dev/null 2>&1; then yum -y install pkgconfig xz || true; fi
67- ARCH="x86_64"; CCACHE_ARCH="linux-x86_64"
68- curl -fsSL -o /tmp/ccache.tar.xz "https://github.com/ccache/ccache/releases/download/v${CCACHE_VER}/ccache-${CCACHE_VER}-${CCACHE_ARCH}.tar.xz"
69- mkdir -p /opt/ccache && tar -C /opt/ccache -xJf /tmp/ccache.tar.xz --strip-components=1
70- export PATH="/opt/ccache/bin:$PATH"; ccache --version; ccache --set-config=max_size=2G || true
71- curl -fsSL -o /tmp/fftw.tar.gz "http://www.fftw.org/fftw-${FFTW_VER}.tar.gz"
72- tar -C /tmp -xzf /tmp/fftw.tar.gz
73- pushd /tmp/fftw-${FFTW_VER}; ./configure --prefix=/opt/fftw --enable-shared --enable-threads
74- make -j"$(nproc)"; make install; popd
75- curl -fsSL -o /tmp/boost.tar.gz "https://archives.boost.io/release/${BOOST_VER_D}/source/boost_${BOOST_VER_U}.tar.gz"
76- tar -C /tmp -xzf /tmp/boost.tar.gz
77- mkdir -p /opt/boost/include; cp -r /tmp/boost_${BOOST_VER_U}/boost /opt/boost/include/
80+
81+ # --- Ensure ccache & ninja exist inside the manylinux container ---
82+ have_ccache=0
83+ if command -v dnf >/dev/null 2>&1; then
84+ dnf -y install ccache pkgconfig ninja-build || true
85+ elif command -v yum >/dev/null 2>&1; then
86+ yum -y install ccache pkgconfig ninja-build || true
87+ elif command -v microdnf >/dev/null 2>&1; then
88+ microdnf -y install ccache pkgconfig ninja-build || true
89+ fi
90+ if command -v ccache >/dev/null 2>&1; then
91+ have_ccache=1
92+ else
93+ # Fallback: fetch a static ccache binary (no package manager needed)
94+ arch="$(uname -m)"
95+ ver="4.11.3"
96+ url_x86_64="https://github.com/ccache/ccache/releases/download/v${ver}/ccache-${ver}-linux-x86_64.tar.xz"
97+ url_aarch64="https://github.com/ccache/ccache/releases/download/v${ver}/ccache-${ver}-linux-aarch64.tar.xz"
98+ url="${url_x86_64}"
99+ [ "$arch" = "aarch64" ] && url="${url_aarch64}"
100+ curl -fsSL "${url}" -o /tmp/ccache.tar.xz
101+ mkdir -p /usr/local/ccache && tar -xJf /tmp/ccache.tar.xz -C /usr/local/ccache --strip-components=1
102+ ln -sf /usr/local/ccache/bin/ccache /usr/local/bin/ccache
103+ have_ccache=1
104+ fi
105+
106+ # Ensure ninja exists too (fallback to portable binary if needed)
107+ if ! command -v ninja >/dev/null 2>&1; then
108+ curl -fsSL -o /usr/local/bin/ninja https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-linux.zip
109+ # some images have no unzip; use busybox if present, else fetch static:
110+ if command -v unzip >/dev/null 2>&1; then
111+ tmpd="$(mktemp -d)" && mv /usr/local/bin/ninja "$tmpd/ninja.zip"
112+ unzip -p "$tmpd/ninja.zip" > /usr/local/bin/ninja && chmod +x /usr/local/bin/ninja
113+ else
114+ # fallback: use curl to a pre-unzipped mirror if you have one; or install unzip via dnf/yum above
115+ echo "ninja fallback requires unzip; please enable unzip in package install above" >&2
116+ exit 1
117+ fi
118+ fi
119+
120+ # --- Build prerequisites we cache (FFTW & Boost headers) ---
121+ mkdir -p /opt/fftw /opt/boost/include
122+ tar -xzf /project/build-cache/fftw-3.3.10.tar.gz -C /tmp
123+ tar -xzf /project/build-cache/boost_1_84_0.tar.gz -C /tmp
124+
125+ pushd /tmp/fftw-3.3.10
126+ ./configure --prefix=/opt/fftw --enable-shared --enable-threads --disable-fortran --disable-mpi
127+ make -j"$(nproc)"
128+ make install
129+ popd
130+
131+ cp -r /tmp/boost_1_84_0/boost /opt/boost/include/
78132
79133 CIBW_ENVIRONMENT_LINUX : >
80- PATH=/opt/ccache/bin:$PATH
81- CCACHE_DIR=/root/.ccache
82134 PKG_CONFIG_PATH=/opt/fftw/lib/pkgconfig
83135 CMAKE_PREFIX_PATH=/opt/fftw
84- CMAKE_ARGS="-DHF_USE_OPENMP=ON -DHF_USE_FFTW_THREADS=ON -DBOOST_INCLUDE_DIR=/opt/boost/include"
85-
136+ CCACHE_DIR=/project/.ccache
137+ CMAKE_ARGS="-G Ninja -DHF_USE_OPENMP=ON -DHF_USE_FFTW_THREADS=ON -DBOOST_INCLUDE_DIR=/opt/boost/include -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
138+ CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
86139 CIBW_REPAIR_WHEEL_COMMAND_LINUX : >
87140 bash -lc 'LD_LIBRARY_PATH=/opt/fftw/lib auditwheel repair -w {dest_dir} {wheel}'
88-
89141 CIBW_TEST_REQUIRES : numpy
90142 CIBW_TEST_COMMAND : |
91143 python - <<'PY'
@@ -101,53 +153,117 @@ jobs:
101153 print("wheel ok", int(n), float(mu))
102154 PY
103155
104- - uses : actions/upload-artifact@v4
156+ - name : Upload Linux x86_64 wheels
157+ uses : actions/upload-artifact@v4
105158 with :
106159 name : dist-wheels-linux-x86_64
107160 path : wheelhouse/*
108161 if-no-files-found : error
109162
163+ # ----- Linux aarch64 (native ARM runner) -----
110164 wheels-linux-aarch64 :
111- name : Build Linux wheels (aarch64, native)
165+ name : Build Linux wheels (aarch64 — native)
166+ # For public repos you can use ubuntu-24.04-arm / ubuntu-22.04-arm.
167+ # For private repos, switch to your self-hosted arm64 runner label.
112168 runs-on : ubuntu-24.04-arm
113- permissions : { contents: read }
169+ permissions :
170+ contents : read
114171 steps :
115- - uses : actions/checkout@v5
116- with : { fetch-depth: 0 }
172+ - uses : actions/checkout@v4
173+ with :
174+ fetch-depth : 0
117175
118- - name : Build wheels with cibuildwheel
119- uses : pypa/cibuildwheel@${{ env.CIBW_VER }}
176+ - name : Restore ccache
177+ uses : actions/cache@v4
178+ with :
179+ path : .ccache
180+ key : ccache-linux-arm64-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake', '**/*.cpp', '**/*.h', 'pyproject.toml') }}
181+
182+ - name : Restore 3rdparty source cache
183+ uses : actions/cache@v4
184+ with :
185+ path : build-cache
186+ key : thirdparty-src-arm64-fftw-3.3.10-boost-1_84_0
187+
188+ - name : Pre-fetch Boost/FFTW (host)
189+ run : |
190+ set -eux
191+ mkdir -p build-cache
192+ test -f build-cache/fftw-3.3.10.tar.gz || \
193+ curl -fsSL -o build-cache/fftw-3.3.10.tar.gz http://www.fftw.org/fftw-3.3.10.tar.gz
194+ test -f build-cache/boost_1_84_0.tar.gz || \
195+ curl -fsSL -o build-cache/boost_1_84_0.tar.gz https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.gz
196+
197+ - name : Build wheels with cibuildwheel (aarch64)
198+ uses : pypa/cibuildwheel@v2.21.3
120199 env :
121- CIBW_BUILD : cp310-manylinux_aarch64 cp311-manylinux_aarch64 cp312-manylinux_aarch64
200+ CIBW_BUILD : cp310-* cp311-* cp312-*
201+ CIBW_SKIP : pp* *-musllinux_*
122202 CIBW_ARCHS_LINUX : aarch64
123203 CIBW_MANYLINUX_AARCH64_IMAGE : manylinux_2_28
124-
125- # identical prebuild steps, just set arch to aarch64 and pick the right ccache tarball
126204 CIBW_BEFORE_ALL_LINUX : |
127205 set -eux
128- if command -v yum >/dev/null 2>&1; then yum -y install pkgconfig xz || true; fi
129- ARCH="aarch64"; CCACHE_ARCH="linux-aarch64"
130- curl -fsSL -o /tmp/ccache.tar.xz "https://github.com/ccache/ccache/releases/download/v${CCACHE_VER}/ccache-${CCACHE_VER}-${CCACHE_ARCH}.tar.xz"
131- mkdir -p /opt/ccache && tar -C /opt/ccache -xJf /tmp/ccache.tar.xz --strip-components=1
132- export PATH="/opt/ccache/bin:$PATH"; ccache --version; ccache --set-config=max_size=2G || true
133- curl -fsSL -o /tmp/fftw.tar.gz "http://www.fftw.org/fftw-${FFTW_VER}.tar.gz"
134- tar -C /tmp -xzf /tmp/fftw.tar.gz
135- pushd /tmp/fftw-${FFTW_VER}; ./configure --prefix=/opt/fftw --enable-shared --enable-threads
136- make -j"$(nproc)"; make install; popd
137- curl -fsSL -o /tmp/boost.tar.gz "https://archives.boost.io/release/${BOOST_VER_D}/source/boost_${BOOST_VER_U}.tar.gz"
138- tar -C /tmp -xzf /tmp/boost.tar.gz
139- mkdir -p /opt/boost/include; cp -r /tmp/boost_${BOOST_VER_U}/boost /opt/boost/include/
206+
207+ # --- Ensure ccache & ninja exist inside the manylinux container ---
208+ have_ccache=0
209+ if command -v dnf >/dev/null 2>&1; then
210+ dnf -y install ccache pkgconfig ninja-build || true
211+ elif command -v yum >/dev/null 2>&1; then
212+ yum -y install ccache pkgconfig ninja-build || true
213+ elif command -v microdnf >/dev/null 2>&1; then
214+ microdnf -y install ccache pkgconfig ninja-build || true
215+ fi
216+ if command -v ccache >/dev/null 2>&1; then
217+ have_ccache=1
218+ else
219+ # Fallback: fetch a static ccache binary (no package manager needed)
220+ arch="$(uname -m)"
221+ ver="4.11.3"
222+ url_x86_64="https://github.com/ccache/ccache/releases/download/v${ver}/ccache-${ver}-linux-x86_64.tar.xz"
223+ url_aarch64="https://github.com/ccache/ccache/releases/download/v${ver}/ccache-${ver}-linux-aarch64.tar.xz"
224+ url="${url_x86_64}"
225+ [ "$arch" = "aarch64" ] && url="${url_aarch64}"
226+ curl -fsSL "${url}" -o /tmp/ccache.tar.xz
227+ mkdir -p /usr/local/ccache && tar -xJf /tmp/ccache.tar.xz -C /usr/local/ccache --strip-components=1
228+ ln -sf /usr/local/ccache/bin/ccache /usr/local/bin/ccache
229+ have_ccache=1
230+ fi
231+
232+ # Ensure ninja exists too (fallback to portable binary if needed)
233+ if ! command -v ninja >/dev/null 2>&1; then
234+ curl -fsSL -o /usr/local/bin/ninja https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-linux.zip
235+ # some images have no unzip; use busybox if present, else fetch static:
236+ if command -v unzip >/dev/null 2>&1; then
237+ tmpd="$(mktemp -d)" && mv /usr/local/bin/ninja "$tmpd/ninja.zip"
238+ unzip -p "$tmpd/ninja.zip" > /usr/local/bin/ninja && chmod +x /usr/local/bin/ninja
239+ else
240+ # fallback: use curl to a pre-unzipped mirror if you have one; or install unzip via dnf/yum above
241+ echo "ninja fallback requires unzip; please enable unzip in package install above" >&2
242+ exit 1
243+ fi
244+ fi
245+
246+ # --- Build prerequisites we cache (FFTW & Boost headers) ---
247+ mkdir -p /opt/fftw /opt/boost/include
248+ tar -xzf /project/build-cache/fftw-3.3.10.tar.gz -C /tmp
249+ tar -xzf /project/build-cache/boost_1_84_0.tar.gz -C /tmp
250+
251+ pushd /tmp/fftw-3.3.10
252+ ./configure --prefix=/opt/fftw --enable-shared --enable-threads --disable-fortran --disable-mpi
253+ make -j"$(nproc)"
254+ make install
255+ popd
256+
257+ cp -r /tmp/boost_1_84_0/boost /opt/boost/include/
140258
141259 CIBW_ENVIRONMENT_LINUX : >
142- PATH=/opt/ccache/bin:$PATH
143- CCACHE_DIR=/root/.ccache
144260 PKG_CONFIG_PATH=/opt/fftw/lib/pkgconfig
145261 CMAKE_PREFIX_PATH=/opt/fftw
146- CMAKE_ARGS="-DHF_USE_OPENMP=ON -DHF_USE_FFTW_THREADS=ON -DBOOST_INCLUDE_DIR=/opt/boost/include"
147-
262+ CCACHE_DIR=/project/.ccache
263+ CMAKE_ARGS="-G Ninja -DHF_USE_OPENMP=ON -DHF_USE_FFTW_THREADS=ON -DBOOST_INCLUDE_DIR=/opt/boost/include -DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
264+ CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
148265 CIBW_REPAIR_WHEEL_COMMAND_LINUX : >
149266 bash -lc 'LD_LIBRARY_PATH=/opt/fftw/lib auditwheel repair -w {dest_dir} {wheel}'
150-
151267 CIBW_TEST_REQUIRES : numpy
152268 CIBW_TEST_COMMAND : |
153269 python - <<'PY'
@@ -163,12 +279,14 @@ jobs:
163279 print("wheel ok", int(n), float(mu))
164280 PY
165281
166- - uses : actions/upload-artifact@v4
282+ - name : Upload Linux aarch64 wheels
283+ uses : actions/upload-artifact@v4
167284 with :
168285 name : dist-wheels-linux-aarch64
169286 path : wheelhouse/*
170287 if-no-files-found : error
171288
289+ # ----- macOS (Intel/Apple Silicon) -----
172290 wheels-macos :
173291 name : Build macOS wheels (Intel/Apple Silicon)
174292 strategy :
@@ -181,33 +299,24 @@ jobs:
181299 permissions :
182300 contents : read
183301 steps :
184- - uses : actions/checkout@v5
302+ - uses : actions/checkout@v4
185303 with :
186304 fetch-depth : 0
187305
188- # Homebrew-only on macOS (latest formulas)
189306 - name : Install Homebrew deps
190307 env :
191308 HOMEBREW_NO_AUTO_UPDATE : " 1"
192309 run : |
193- set -eux
194- # Keep brew metadata stable during CI run, but accept current formula versions
195310 rm -f "$HOME/Library/Caches/Homebrew/downloads/"*libomp* || true
196- brew install ccache fftw libomp boost cmake ninja || true
197- # Make sure ccache is on PATH and usable
198- echo 'export PATH="/opt/homebrew/opt/ccache/libexec:$PATH"' >> "$HOME/.bash_profile" || true
199- echo 'export PATH="/usr/local/opt/ccache/libexec:$PATH"' >> "$HOME/.bash_profile" || true
200- export PATH="/opt/homebrew/opt/ccache/libexec:$PATH:/usr/local/opt/ccache/libexec:$PATH"
201- ccache --version || true
311+ brew install fftw libomp boost cmake ninja || true
202312
203313 - name : Build wheels with cibuildwheel
204- uses : pypa/cibuildwheel@${{ env.CIBW_VER }}
314+ uses : pypa/cibuildwheel@v2.21.3
205315 env :
206316 CIBW_BUILD : cp310-* cp311-* cp312-*
207317 CIBW_SKIP : pp*
208318 CIBW_ARCHS_MACOS : native
209319 CIBW_ENVIRONMENT_MACOS : >
210- PATH=/opt/homebrew/opt/ccache/libexec:/usr/local/opt/ccache/libexec:$PATH
211320 PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig:/usr/local/lib/pkgconfig
212321 CMAKE_ARGS="-DHF_USE_OPENMP=ON -DHF_USE_FFTW_THREADS=ON -DCMAKE_OSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET}"
213322 CIBW_REPAIR_WHEEL_COMMAND_MACOS : >
@@ -234,11 +343,13 @@ jobs:
234343 path : wheelhouse/*
235344 if-no-files-found : error
236345
346+ # ----- Publish to PyPI -----
237347 publish :
238348 name : Publish to PyPI
239349 needs : [sdist, wheels-linux-x86_64, wheels-linux-aarch64, wheels-macos]
240350 runs-on : ubuntu-latest
241- environment : cpp_hf_env # must match Trusted Publisher environment on PyPI
351+ # 🔐 Ensure the OIDC token includes the environment claim
352+ environment : cpp_hf_env
242353 permissions :
243354 contents : read
244355 id-token : write
0 commit comments