Skip to content

Commit 5dd3bd9

Browse files
committed
.github/workflows/dist.yml: Build musllinux and windows wheels
1 parent f5dc544 commit 5dd3bd9

File tree

1 file changed

+261
-7
lines changed

1 file changed

+261
-7
lines changed

.github/workflows/dist.yml

Lines changed: 261 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ jobs:
6060
# Non-Python packages to install as spkgs
6161
TARGETS_PRE: gmp mpfr normaliz
6262
# Disable building PyPy wheels on all platforms
63-
# Disable musllinux until #33083 provides alpine package information
64-
CIBW_SKIP: "pp* *-musllinux*"
63+
CIBW_SKIP: "pp*"
6564
#
6665
CIBW_ARCHS: ${{ matrix.arch }}
6766
# https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python
@@ -70,6 +69,10 @@ jobs:
7069
CIBW_ENVIRONMENT: "PATH=$(pwd)/local/bin:$PATH CPATH=$(pwd)/local/include:$CPATH LIBRARY_PATH=$(pwd)/local/lib:$LIBRARY_PATH LD_LIBRARY_PATH=$(pwd)/local/lib:$LD_LIBRARY_PATH PKG_CONFIG_PATH=$(pwd)/local/share/pkgconfig:$PKG_CONFIG_PATH ACLOCAL_PATH=/usr/share/aclocal"
7170
# Use 'build', not 'pip wheel'
7271
CIBW_BUILD_FRONTEND: build
72+
CIBW_REPAIR_WHEEL_COMMAND_LINUX: "set -x && export LD_LIBRARY_PATH=$(pwd)/prefix/lib:$LD_LIBRARY_PATH && auditwheel -v -v -v -v repair -w {dest_dir} {wheel}"
73+
CIBW_REPAIR_WHEEL_COMMAND_MACOS: "set -x && export DYLD_FALLBACK_LIBRARY_PATH=$(pwd)/prefix/lib:$DYLD_FALLBACK_LIBRARY_PATH && delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}"
74+
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
75+
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28
7376
steps:
7477
- uses: actions/checkout@v4
7578
with:
@@ -89,6 +92,39 @@ jobs:
8992
python-version: "3.8 - 3.12"
9093
update-environment: false
9194

95+
- name: Retrieve configure tarball cache
96+
id: cache-configure
97+
uses: actions/cache/restore@v4
98+
with:
99+
path: |
100+
build/pkgs/configure
101+
upstream/configure*
102+
key: >-
103+
configure-build=${{
104+
hashFiles('build',
105+
'configure.ac',
106+
'm4')
107+
}}
108+
109+
- name: Bootstrap
110+
if: steps.cache-configure.outputs.cache-hit != 'true'
111+
# Patch python3 spkg-configure to allow Python 3.8.0 during the CIBW_BEFORE_ALL phase
112+
run: |
113+
export PATH=$(pwd)/build/bin:$PATH
114+
eval $(sage-print-system-package-command auto --sudo --yes update)
115+
eval $(sage-print-system-package-command auto --sudo --yes --no-install-recommends --spkg install _bootstrap bzip2 xz liblzma)
116+
sed -i.bak '/m4_pushdef.*MIN_VERSION/s/3[0-9.]*/3.8.0/' build/pkgs/python3/spkg-configure.m4
117+
./bootstrap -s
118+
119+
- name: Save configure tarball cache
120+
if: steps.cache-configure.outputs.cache-hit != 'true'
121+
uses: actions/cache/save@v4
122+
with:
123+
path: |
124+
build/pkgs/configure
125+
upstream/configure*
126+
key: ${{ steps.cache-configure.outputs.cache-primary-key }}
127+
92128
- name: Build platform wheels
93129
# We build the wheel from the sdist.
94130
# But we must run cibuildwheel with the unpacked source directory, not a tarball,
@@ -98,33 +134,251 @@ jobs:
98134
# https://cibuildwheel.readthedocs.io/en/stable/options/#before-all
99135
run: |
100136
"${{ steps.python.outputs.python-path }}" -m pip install pipx
137+
if [ ! -x ./configure ]; then ./bootstrap -D; fi
138+
touch configure
101139
export PATH=build/bin:$PATH
102-
export CIBW_BEFORE_ALL="( $(sage-print-system-package-command debian --yes --no-install-recommends install $(sage-get-system-packages debian $SPKGS)) || $(sage-print-system-package-command fedora --yes --no-install-recommends install $(sage-get-system-packages fedora $SPKGS | sed s/pkg-config/pkgconfig/)) || ( $(sage-print-system-package-command homebrew --yes --no-install-recommends install $(sage-get-system-packages homebrew $SPKGS)) || $(sage-print-system-package-command alpine --yes --no-install-recommends install $(sage-get-system-packages alpine $SPKGS)) || echo error ignored) ) && ./bootstrap && ./configure --enable-build-as-root --enable-fat-binary && MAKE=\"make -j6\" make V=0 $TARGETS_PRE"
140+
export CIBW_BEFORE_ALL="( $(sage-print-system-package-command debian --yes --no-install-recommends install $(sage-get-system-packages debian $SPKGS)) || $(sage-print-system-package-command fedora --yes --no-install-recommends install $(sage-get-system-packages fedora $SPKGS | sed s/pkg-config/pkgconfig/)) || ( $(sage-print-system-package-command homebrew --yes --no-install-recommends install $(sage-get-system-packages homebrew $SPKGS)) || $(sage-print-system-package-command alpine --yes --no-install-recommends install $(sage-get-system-packages alpine $SPKGS)) || echo error ignored) ) && ./configure --enable-build-as-root --enable-fat-binary --disable-python-distutils-check && MAKE=\"make -j6\" make V=0 $TARGETS_PRE"
103141
mkdir -p unpacked
104142
for pkg in pynormaliz; do
105143
(cd unpacked && tar xfz - ) < dist/$pkg*.tar.gz
106-
"${{ steps.python.outputs.python-path }}" -m pipx run cibuildwheel==2.18.0 unpacked/$pkg*
144+
"${{ steps.python.outputs.python-path }}" -m pipx run cibuildwheel==2.21.3 unpacked/$pkg*
145+
done
146+
147+
- uses: actions/upload-artifact@v4
148+
if: always()
149+
with:
150+
name: ${{ matrix.os }}-${{ matrix.build }}-${{ matrix.arch }}-wheels
151+
path: ./wheelhouse/*.whl
152+
153+
build_wheels_windows:
154+
name: Build wheels on ${{ matrix.os }} using ${{ matrix.env }}
155+
runs-on: ${{ matrix.os }}
156+
needs: sdists_for_pypi
157+
strategy:
158+
fail-fast: false
159+
matrix:
160+
include:
161+
- os: windows-2022
162+
msystem: ucrt64
163+
env: ucrt-x86_64
164+
arch: auto
165+
build: "win_*64"
166+
- os: windows-11-arm
167+
msystem: clangarm64
168+
env: clang-aarch64
169+
arch: auto
170+
build: "win_*64"
171+
env:
172+
# SPKGs to install as system packages
173+
SPKGS: _bootstrap _prereq
174+
# Non-Python packages to install as spkgs
175+
TARGETS_PRE: normaliz
176+
# Disable building PyPy wheels on all platforms
177+
CIBW_SKIP: "pp*"
178+
#
179+
CIBW_ARCHS: ${{ matrix.arch }}
180+
# https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python
181+
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9"
182+
# Run before wheel build
183+
CIBW_BEFORE_BUILD_WINDOWS: |
184+
pip install delvewheel
185+
# Environment during wheel build
186+
# PYTHONUTF8=1 is for delvewheel
187+
CIBW_ENVIRONMENT: >-
188+
PATH="D:\\a\\sage\\sage\\sage-local\\bin;D:\\a\\sage\\sage\\build\\bin;$PATH"
189+
INCLUDE="D:\\a\\sage\\sage\\sage-local\\include;%INCLUDE%"
190+
LIB="D:\\a\\sage\\sage\\sage-local\\bin;D:\\a\\sage\\sage\\sage-local\\lib;%LIB%"
191+
PKG_CONFIG_PATH=$(pwd)/prefix/lib/pkgconfig:$PKG_CONFIG_PATH
192+
ACLOCAL_PATH=/usr/share/aclocal
193+
PIP_FIND_LINKS=D:\\a\\sage\\sage\\wheelhouse' 'D:\\a\\sage\\sage\\dist
194+
SAGE_NUM_THREADS=6
195+
PYTHONUTF8=1
196+
# Use 'build', not 'pip wheel'
197+
CIBW_BUILD_FRONTEND: build
198+
# CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair -vv --custom-patch -w {dest_dir} {wheel}"
199+
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair -vv -w {dest_dir} {wheel}"
200+
#
201+
CIBW_PLATFORM: windows
202+
steps:
203+
- uses: actions/checkout@v4
204+
with:
205+
repository: passagemath/passagemath
206+
ref: main
207+
208+
- uses: actions/download-artifact@v4
209+
with:
210+
name: dist
211+
path: dist
212+
213+
- uses: msys2/setup-msys2@v2
214+
name: Setup msys2
215+
with:
216+
install: >-
217+
mingw-w64-${{ matrix.env }}-gcc
218+
autotools
219+
python
220+
python-pip
221+
python-setuptools
222+
patch
223+
bison
224+
mingw-w64-${{ matrix.env }}-cmake
225+
mingw-w64-${{ matrix.env }}-ninja
226+
mingw-w64-${{ matrix.env }}-gtest
227+
mingw-w64-${{ matrix.env }}-ncurses
228+
mingw-w64-${{ matrix.env }}-readline
229+
mingw-w64-${{ matrix.env }}-texinfo
230+
msystem: ${{ matrix.msystem }}
231+
path-type: inherit
232+
233+
- name: Retrieve configure tarball cache
234+
id: cache-configure
235+
uses: actions/cache/restore@v4
236+
with:
237+
path: |
238+
build/pkgs/configure
239+
upstream/configure*
240+
key: >-
241+
configure-build=${{
242+
hashFiles('build',
243+
'configure.ac',
244+
'm4')
245+
}}
246+
247+
- name: Bootstrap
248+
if: steps.cache-configure.outputs.cache-hit != 'true'
249+
# Patch python3 spkg-configure to allow Python 3.8.0 during the CIBW_BEFORE_ALL phase
250+
run: |
251+
export PATH=$(pwd)/build/bin:$PATH
252+
eval $(sage-print-system-package-command auto --yes update)
253+
eval $(sage-print-system-package-command auto --yes --no-install-recommends --spkg install _bootstrap bzip2 xz liblzma)
254+
sed -i.bak '/m4_pushdef.*MIN_VERSION/s/3[0-9.]*/3.8.0/' build/pkgs/python3/spkg-configure.m4
255+
./bootstrap -s
256+
shell: msys2 {0}
257+
258+
- name: Save configure tarball cache
259+
if: steps.cache-configure.outputs.cache-hit != 'true'
260+
uses: actions/cache/save@v4
261+
with:
262+
path: |
263+
build/pkgs/configure
264+
upstream/configure*
265+
key: ${{ steps.cache-configure.outputs.cache-primary-key }}
266+
267+
- name: Retrieve SAGE_LOCAL cache
268+
id: cache-sage-local
269+
uses: actions/cache/restore@v4
270+
with:
271+
path: |
272+
config.status
273+
sage-local
274+
key: >-
275+
${{ runner.os }}-cibuildwheel-${{ matrix.arch }}-build=${{
276+
hashFiles('build',
277+
'configure.ac',
278+
'm4')
279+
}}
280+
restore-keys: |
281+
${{ runner.os }}-cibuildwheel-${{ matrix.arch }}
282+
283+
- name: Unpack and prepare
284+
id: unpack
285+
# We build the wheels from the sdists so that MANIFEST filtering becomes effective.
286+
# But we must run cibuildwheel with the unpacked source directory, not a tarball,
287+
# so that SAGE_ROOT is copied into the build containers.
288+
#
289+
# In the CIBW_BEFORE_ALL phase, we install libraries using the Sage distribution.
290+
# https://cibuildwheel.readthedocs.io/en/stable/options/#before-all
291+
# For Linux, this is repeated for each of the packages that we build wheels for
292+
# because CIBW starts with a fresh container on each invocation.
293+
# Therefore we cache it in a directory mounted from the host: /host
294+
# https://cibuildwheel.pypa.io/en/stable/faq/#linux-builds-in-containers
295+
#
296+
# - configure --with-sage-venv makes the SAGE_VENV separate from SAGE_LOCAL.
297+
# SAGE_LOCAL is put in PATH for the wheel building.
298+
# SAGE_VENV must not be in PATH so it does not shadow cibuildwheel's build tools.
299+
#
300+
run: |
301+
if [ ! -x ./configure ]; then ./bootstrap -D; fi
302+
touch configure
303+
SAGE_LOCAL=$(pwd)/sage-local
304+
# We set the installation records to the same mtime so that no rebuilds due to dependencies
305+
# among these packages are triggered.
306+
dummy="$SAGE_LOCAL"/var/lib/sage/installed/.dummy
307+
if [ -f "$dummy" ]; then
308+
touch "$dummy"
309+
for tree in "$SAGE_LOCAL" "$SAGE_LOCAL"/var/lib/sage/venv*; do
310+
inst="$tree"/var/lib/sage/installed
311+
if [ -d "$inst" ]; then
312+
# -r is --reference; the macOS version of touch does not accept the long option.
313+
(cd "$inst" && touch -r "$dummy" .dummy *)
314+
# Show what has been built already.
315+
ls -l "$tree" "$inst"
316+
fi
317+
done
318+
fi
319+
320+
export PATH=build/bin:$PATH
321+
echo CIBW_BEFORE_ALL="msys2 tools/cibw_before_all_windows.sh" >> "$GITHUB_ENV"
322+
mkdir -p unpacked
323+
set -x
324+
for sdist in dist/$pkg*.tar.gz; do
325+
(cd unpacked && tar xfz - && base=${sdist#dist/} && mv ${base%.tar.gz} ${base%-*}) < $sdist
107326
done
327+
shell: msys2 {0}
328+
329+
- name: pynormaliz wheels
330+
id: pynormaliz
331+
uses: pypa/cibuildwheel@v2.23.0
332+
with:
333+
package-dir: unpacked/pynormaliz
334+
335+
- name: Save SAGE_LOCAL cache
336+
if: (success() || failure()) && steps.unpack.outcome == 'success'
337+
uses: actions/cache/save@v4
338+
with:
339+
path: |
340+
config.status
341+
sage-local
342+
!sage-local/lib64
343+
key: ${{ steps.cache-sage-local.outputs.cache-primary-key }}
108344

109345
- uses: actions/upload-artifact@v4
110346
with:
111347
name: ${{ matrix.os }}-${{ matrix.arch }}-wheels
112348
path: ./wheelhouse/*.whl
113349

350+
- uses: actions/upload-artifact@v4
351+
if: always()
352+
with:
353+
name: unpacked-${{ matrix.os }}
354+
path: ./unpacked
355+
356+
- uses: actions/upload-artifact@v4
357+
if: always()
358+
with:
359+
name: sage-local-${{ matrix.os }}
360+
path: ./sage-local
361+
362+
- uses: actions/upload-artifact@v4
363+
if: always()
364+
with:
365+
name: logs-${{ matrix.os }}
366+
path: ./logs
367+
114368
pypi-publish:
115369
# This needs to be a separate job because pypa/gh-action-pypi-publish cannot run on macOS
116370
# https://github.com/pypa/gh-action-pypi-publish
117371
name: Upload wheels to PyPI
118-
needs: build_wheels
119-
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
372+
needs: [build_wheels, build_wheels_windows]
373+
if: (success() || failure()) && github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
120374
runs-on: ubuntu-latest
121375
env:
122376
CAN_DEPLOY: ${{ secrets.PYPI_PASSWORD != '' }}
123377
steps:
124378

125379
- uses: actions/download-artifact@v4
126380
with:
127-
pattern: "*-*-wheels"
381+
pattern: "*-wheels"
128382
path: wheelhouse
129383
merge-multiple: true
130384

0 commit comments

Comments
 (0)