Skip to content

.github/workflows/dist.yml: Build Windows wheels #22

.github/workflows/dist.yml: Build Windows wheels

.github/workflows/dist.yml: Build Windows wheels #22

Workflow file for this run

name: Distributions
on:
push:
pull_request:
workflow_dispatch:
concurrency:
# Cancel previous runs of this workflow for the same branch
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
sdists_for_pypi:
name: Build sdist (and upload to PyPI on release tags)
runs-on: ubuntu-latest
env:
CAN_DEPLOY: ${{ secrets.PYPI_PASSWORD != '' }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- name: make sdist
run: |
python3 -m pip install build
python3 -m build --sdist
- uses: actions/upload-artifact@v4
with:
path: "dist/*.tar.gz"
name: dist
- uses: pypa/gh-action-pypi-publish@release/v1
with:
user: ${{ secrets.PYPI_USERNAME }}
password: ${{ secrets.PYPI_PASSWORD }}
skip_existing: true
verbose: true
if: env.CAN_DEPLOY == 'true' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
build_wheels:
name: Build wheels on ${{ matrix.os }}, arch ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
needs: sdists_for_pypi
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
arch: x86_64
- os: ubuntu-latest
arch: i686
- os: ubuntu-24.04-arm
arch: aarch64
- os: macos-13
arch: x86_64
- os: macos-14
arch: arm64
env:
# SPKGs to install as system packages
SPKGS: _bootstrap _prereq
# Non-Python packages to install as spkgs
TARGETS_PRE: gmp mpfr normaliz
# Disable building PyPy wheels on all platforms
CIBW_SKIP: "pp*"
#
CIBW_ARCHS: ${{ matrix.arch }}
# https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9"
# Environment during wheel build
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"
# Use 'build', not 'pip wheel'
CIBW_BUILD_FRONTEND: build
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}"
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}"
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28
steps:
- uses: actions/checkout@v4
with:
repository: passagemath/passagemath
#ref: main
ref: refs/pull/1191/merge
- uses: actions/download-artifact@v4
with:
name: dist
path: dist
- uses: actions/setup-python@v5
# As of 2024-02-03, the macOS M1 runners do not have preinstalled python or pipx.
# Installing pipx follows the approach of https://github.com/pypa/cibuildwheel/pull/1743
id: python
with:
python-version: "3.8 - 3.12"
update-environment: false
- name: Retrieve configure tarball cache
id: cache-configure
uses: actions/cache/restore@v4
with:
path: |
build/pkgs/configure
upstream/configure*
key: >-
configure-build=${{
hashFiles('build',
'configure.ac',
'm4')
}}
- name: Bootstrap
if: steps.cache-configure.outputs.cache-hit != 'true'
# Patch python3 spkg-configure to allow Python 3.8.0 during the CIBW_BEFORE_ALL phase
run: |
export PATH=$(pwd)/build/bin:$PATH
eval $(sage-print-system-package-command auto --sudo --yes update)
eval $(sage-print-system-package-command auto --sudo --yes --no-install-recommends --spkg install _bootstrap bzip2 xz liblzma)
sed -i.bak '/m4_pushdef.*MIN_VERSION/s/3[0-9.]*/3.8.0/' build/pkgs/python3/spkg-configure.m4
./bootstrap -s
- name: Save configure tarball cache
if: steps.cache-configure.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
build/pkgs/configure
upstream/configure*
key: ${{ steps.cache-configure.outputs.cache-primary-key }}
- name: Build platform wheels
# We build the wheel from the sdist.
# But we must run cibuildwheel with the unpacked source directory, not a tarball,
# so that SAGE_ROOT is copied into the build containers.
#
# In the CIBW_BEFORE_ALL phase, we install libraries using the Sage distribution.
# https://cibuildwheel.readthedocs.io/en/stable/options/#before-all
run: |
"${{ steps.python.outputs.python-path }}" -m pip install pipx
if [ ! -x ./configure ]; then ./bootstrap -D; fi
touch configure
export PATH=build/bin:$PATH
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"
mkdir -p unpacked
for pkg in pynormaliz; do
(cd unpacked && tar xfz - ) < dist/$pkg*.tar.gz
"${{ steps.python.outputs.python-path }}" -m pipx run cibuildwheel==2.21.3 unpacked/$pkg*
done
- uses: actions/upload-artifact@v4
if: always()
with:
name: ${{ matrix.os }}-${{ matrix.build }}-${{ matrix.arch }}-wheels
path: ./wheelhouse/*.whl
build_wheels_windows:
name: Build wheels on ${{ matrix.os }} using ${{ matrix.env }}
runs-on: ${{ matrix.os }}
needs: sdists_for_pypi
strategy:
fail-fast: false
matrix:
include:
- os: windows-2022
msystem: ucrt64
env: ucrt-x86_64
arch: auto
build: "win_*64"
- os: windows-11-arm
msystem: clangarm64
env: clang-aarch64
arch: auto
build: "win_*64"
env:
# SPKGs to install as system packages
SPKGS: _bootstrap _prereq
# Non-Python packages to install as spkgs
TARGETS_PRE: normaliz
# Disable building PyPy wheels on all platforms
CIBW_SKIP: "pp*"
#
CIBW_ARCHS: ${{ matrix.arch }}
# https://cibuildwheel.readthedocs.io/en/stable/options/#requires-python
CIBW_PROJECT_REQUIRES_PYTHON: ">=3.9"
# Run before wheel build
CIBW_BEFORE_BUILD_WINDOWS: |
pip install delvewheel
# Environment during wheel build
# PYTHONUTF8=1 is for delvewheel
CIBW_ENVIRONMENT: >-
PATH="D:\\a\\sage\\sage\\sage-local\\bin;D:\\a\\sage\\sage\\build\\bin;$PATH"
INCLUDE="D:\\a\\sage\\sage\\sage-local\\include;%INCLUDE%"
LIB="D:\\a\\sage\\sage\\sage-local\\bin;D:\\a\\sage\\sage\\sage-local\\lib;%LIB%"
PKG_CONFIG_PATH=$(pwd)/prefix/lib/pkgconfig:$PKG_CONFIG_PATH
ACLOCAL_PATH=/usr/share/aclocal
PIP_FIND_LINKS=D:\\a\\sage\\sage\\wheelhouse' 'D:\\a\\sage\\sage\\dist
SAGE_NUM_THREADS=6
PYTHONUTF8=1
# Use 'build', not 'pip wheel'
CIBW_BUILD_FRONTEND: build
# CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair -vv --custom-patch -w {dest_dir} {wheel}"
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair -vv -w {dest_dir} {wheel}"
#
CIBW_PLATFORM: windows
steps:
- uses: actions/checkout@v4
with:
repository: passagemath/passagemath
#ref: main
ref: refs/pull/1191/merge
- uses: actions/download-artifact@v4
with:
name: dist
path: dist
- uses: msys2/setup-msys2@v2
name: Setup msys2
with:
install: >-
mingw-w64-${{ matrix.env }}-gcc
autotools
python
python-pip
python-setuptools
patch
bison
mingw-w64-${{ matrix.env }}-cmake
mingw-w64-${{ matrix.env }}-ninja
mingw-w64-${{ matrix.env }}-gtest
mingw-w64-${{ matrix.env }}-ncurses
mingw-w64-${{ matrix.env }}-readline
mingw-w64-${{ matrix.env }}-texinfo
msystem: ${{ matrix.msystem }}
path-type: inherit
- name: Retrieve configure tarball cache
id: cache-configure
uses: actions/cache/restore@v4
with:
path: |
build/pkgs/configure
upstream/configure*
key: >-
configure-build=${{
hashFiles('build',
'configure.ac',
'm4')
}}
- name: Bootstrap
if: steps.cache-configure.outputs.cache-hit != 'true'
# Patch python3 spkg-configure to allow Python 3.8.0 during the CIBW_BEFORE_ALL phase
run: |
export PATH=$(pwd)/build/bin:$PATH
eval $(sage-print-system-package-command auto --yes update)
eval $(sage-print-system-package-command auto --yes --no-install-recommends --spkg install _bootstrap bzip2 xz liblzma)
sed -i.bak '/m4_pushdef.*MIN_VERSION/s/3[0-9.]*/3.8.0/' build/pkgs/python3/spkg-configure.m4
./bootstrap -s
shell: msys2 {0}
- name: Save configure tarball cache
if: steps.cache-configure.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
build/pkgs/configure
upstream/configure*
key: ${{ steps.cache-configure.outputs.cache-primary-key }}
- name: Retrieve SAGE_LOCAL cache
id: cache-sage-local
uses: actions/cache/restore@v4
with:
path: |
config.status
sage-local
key: >-
${{ runner.os }}-cibuildwheel-${{ matrix.arch }}-build=${{
hashFiles('build',
'configure.ac',
'm4')
}}
restore-keys: |
${{ runner.os }}-cibuildwheel-${{ matrix.arch }}
- name: Unpack and prepare
id: unpack
# We build the wheels from the sdists so that MANIFEST filtering becomes effective.
# But we must run cibuildwheel with the unpacked source directory, not a tarball,
# so that SAGE_ROOT is copied into the build containers.
#
# In the CIBW_BEFORE_ALL phase, we install libraries using the Sage distribution.
# https://cibuildwheel.readthedocs.io/en/stable/options/#before-all
# For Linux, this is repeated for each of the packages that we build wheels for
# because CIBW starts with a fresh container on each invocation.
# Therefore we cache it in a directory mounted from the host: /host
# https://cibuildwheel.pypa.io/en/stable/faq/#linux-builds-in-containers
#
# - configure --with-sage-venv makes the SAGE_VENV separate from SAGE_LOCAL.
# SAGE_LOCAL is put in PATH for the wheel building.
# SAGE_VENV must not be in PATH so it does not shadow cibuildwheel's build tools.
#
run: |
if [ ! -x ./configure ]; then ./bootstrap -D; fi
touch configure
SAGE_LOCAL=$(pwd)/sage-local
# We set the installation records to the same mtime so that no rebuilds due to dependencies
# among these packages are triggered.
dummy="$SAGE_LOCAL"/var/lib/sage/installed/.dummy
if [ -f "$dummy" ]; then
touch "$dummy"
for tree in "$SAGE_LOCAL" "$SAGE_LOCAL"/var/lib/sage/venv*; do
inst="$tree"/var/lib/sage/installed
if [ -d "$inst" ]; then
# -r is --reference; the macOS version of touch does not accept the long option.
(cd "$inst" && touch -r "$dummy" .dummy *)
# Show what has been built already.
ls -l "$tree" "$inst"
fi
done
fi
export PATH=build/bin:$PATH
echo CIBW_BEFORE_ALL="msys2 tools/cibw_before_all_windows.sh" >> "$GITHUB_ENV"
mkdir -p unpacked
set -x
for sdist in dist/$pkg*.tar.gz; do
(cd unpacked && tar xfz - && base=${sdist#dist/} && mv ${base%.tar.gz} ${base%-*}) < $sdist
done
shell: msys2 {0}
- name: pynormaliz wheels
id: pynormaliz
uses: pypa/[email protected]
with:
package-dir: unpacked/pynormaliz
- name: Save SAGE_LOCAL cache
if: (success() || failure()) && steps.unpack.outcome == 'success'
uses: actions/cache/save@v4
with:
path: |
config.status
sage-local
!sage-local/lib64
key: ${{ steps.cache-sage-local.outputs.cache-primary-key }}
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-${{ matrix.arch }}-wheels
path: ./wheelhouse/*.whl
- uses: actions/upload-artifact@v4
if: always()
with:
name: unpacked-${{ matrix.os }}
path: ./unpacked
- uses: actions/upload-artifact@v4
if: always()
with:
name: sage-local-${{ matrix.os }}
path: ./sage-local
- uses: actions/upload-artifact@v4
if: always()
with:
name: logs-${{ matrix.os }}
path: ./logs
pypi-publish:
# This needs to be a separate job because pypa/gh-action-pypi-publish cannot run on macOS
# https://github.com/pypa/gh-action-pypi-publish
name: Upload wheels to PyPI
needs: [build_wheels, build_wheels_windows]
if: (success() || failure()) && github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
runs-on: ubuntu-latest
env:
CAN_DEPLOY: ${{ secrets.PYPI_PASSWORD != '' }}
steps:
- uses: actions/download-artifact@v4
with:
pattern: "*-wheels"
path: wheelhouse
merge-multiple: true
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: ${{ secrets.PYPI_USERNAME }}
password: ${{ secrets.PYPI_PASSWORD }}
packages_dir: wheelhouse/
skip_existing: true
verbose: true
if: env.CAN_DEPLOY == 'true'