Skip to content

Commit 442f5b8

Browse files
committed
Add Windows on ARM wheels.
1 parent 2e84fc5 commit 442f5b8

7 files changed

Lines changed: 135 additions & 27 deletions

File tree

.github/workflows/buildwheel.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
fail-fast: false
1212
matrix:
13-
os: [ubuntu-22.04, ubuntu-22.04-arm, windows-2022, macos-15-intel, macos-14]
13+
os: [ubuntu-22.04, ubuntu-22.04-arm, windows-2022, windows-11-arm, macos-15-intel, macos-14]
1414

1515
steps:
1616
- uses: actions/checkout@v6.0.2
@@ -22,7 +22,12 @@ jobs:
2222
- uses: msys2/setup-msys2@v2.30.0
2323
with:
2424
msystem: ucrt64
25-
if: ${{ startsWith( matrix.os , 'windows' ) }}
25+
if: ${{ matrix.os == 'windows-2022' }}
26+
27+
- uses: msys2/setup-msys2@v2.30.0
28+
with:
29+
msystem: clangarm64
30+
if: ${{ matrix.os == 'windows-11-arm' }}
2631

2732
# Install pkgconfig on Windows from choco rather than from msys and
2833
# avoid using the Strawberry one.
@@ -41,7 +46,7 @@ jobs:
4146
uses: pypa/cibuildwheel@298ed2fb2c105540f5ed055e8a6ad78d82dd3a7e # v3.3.1
4247
env:
4348
# override setting in pyproject.toml to use msys2 instead of msys64 bash
44-
CIBW_BEFORE_ALL_WINDOWS: msys2 -c bin/cibw_before_all_windows.sh
49+
CIBW_BEFORE_ALL_WINDOWS: ${{ matrix.os == 'windows-11-arm' && 'msys2 -c bin/cibw_before_all_windows_arm64.sh' || 'msys2 -c bin/cibw_before_all_windows_amd64.sh' }}
4550

4651
- uses: actions/upload-artifact@v7
4752
with:
@@ -81,12 +86,16 @@ jobs:
8186
ubuntu-24.04-arm,
8287
windows-2022,
8388
windows-2025,
89+
windows-11-arm,
8490
macos-15-intel,
8591
macos-14,
8692
macos-15,
8793
]
8894
# This list to be kept in sync with python-requires in pyproject.toml.
8995
python-version: ['3.11', '3.12', '3.13', '3.13t', '3.14', '3.14t', 'pypy3.11']
96+
exclude:
97+
- os: windows-11-arm
98+
python-version: pypy3.11
9099

91100
steps:
92101
- uses: actions/setup-python@v6

bin/build_dependencies_unix.sh

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ set -o errexit
1818

1919
SKIP_GMP=no
2020
SKIP_MPFR=no
21+
PATCH_GMP_C23=no
22+
PATCH_LDD=no
23+
GMP_FAT_ARG="--enable-fat"
24+
HOST_ARG=
2125

2226
USE_GMP=gmp
2327
PATCH_GMP_ARM64=no
@@ -38,6 +42,8 @@ do
3842
echo " --host <HOST> - set the host (target) for GMP build"
3943
echo " --skip-gmp - skip building GMP"
4044
echo " --skip-mpfr - skip building MPFR"
45+
echo " --disable-fat - disable building fat binaries"
46+
echo " --patch-ldd - patch flint shared linking for mingw on arm64"
4147
echo
4248
echo "Legacy options:"
4349
echo " --gmp gmp - build based on GMP (default)"
@@ -84,6 +90,11 @@ do
8490
SKIP_MPFR=yes
8591
shift
8692
;;
93+
--disable-fat)
94+
# Needed for the ARM64 Windows build under clangarm64.
95+
GMP_FAT_ARG="--disable-assembly"
96+
shift
97+
;;
8798
--patch-gmp-arm64)
8899
# Needed only for GMP 6.2.1 on OSX arm64 (Apple M1) hardware
89100
# As of GMP 6.3.0 this patch is no longer needed
@@ -95,6 +106,11 @@ do
95106
PATCH_GMP_C23=yes
96107
shift
97108
;;
109+
--patch-ldd)
110+
# Needed only for the FLINT shared build on mingw arm64.
111+
PATCH_LDD=yes
112+
shift
113+
;;
98114
--use-gmp-github-mirror)
99115
USE_GMP_GITHUB_MIRROR=yes
100116
shift
@@ -191,7 +207,7 @@ if [ "$USE_GMP" = "gmp" ]; then
191207
./configfsf.guess
192208

193209
./configure --prefix=$PREFIX\
194-
--enable-fat\
210+
$GMP_FAT_ARG\
195211
--enable-shared=yes\
196212
--enable-static=no\
197213
--host=$HOST_ARG
@@ -310,6 +326,13 @@ echo
310326
curl -O -L https://github.com/flintlib/flint/releases/download/v$FLINTVER/flint-$FLINTVER.tar.gz
311327
tar xf flint-$FLINTVER.tar.gz
312328
cd flint-$FLINTVER
329+
if [ "$PATCH_LDD" = "yes" ]; then
330+
echo
331+
echo --------------------------------------------
332+
echo " patching FLINT"
333+
echo --------------------------------------------
334+
patch -N -Z -p1 < ../../../bin/patch-flint-windows-arm64-link.diff
335+
fi
313336
./bootstrap.sh
314337
./configure --prefix=$PREFIX\
315338
--host=$HOST_ARG\
Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@ bin/build_dependencies_unix.sh \
2222
# Assumes the standard GitHub Actions Windows 2022 runner layout.
2323
PATH="$PATH:$(find "/c/Program Files/Microsoft Visual Studio/2022/" -name "Hostx86")/x64/"
2424

25-
if [ "${RUNNER_ARCH}" = "ARM64" ]
26-
then
27-
msvc_machine=arm64
28-
else
29-
msvc_machine=x64
30-
fi
31-
3225
mkdir -p .local/lib
3326
cd .local/bin
3427
for dll_file in libgmp-*.dll libmpfr-*.dll libflint*.dll
@@ -46,7 +39,7 @@ do
4639
awk 'NR>19 && $4 != "" {print $4 " @"$1}' ${exports_file} >> ${def_file}
4740
sed -i 's/$/\r/' ${def_file}
4841

49-
lib //def:${def_file} //out:${lib_file} //machine:${msvc_machine}
42+
lib //def:${def_file} //out:${lib_file} //machine:x64
5043
rm ${exports_file} ${def_file} ${lib_name}.exp
5144
mv ${lib_file} ../lib/${name}.lib
5245
done
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
5+
pacman -S --noconfirm \
6+
mingw-w64-clang-aarch64-toolchain\
7+
mingw-w64-clang-aarch64-tools-git\
8+
m4\
9+
make\
10+
base-devel\
11+
autoconf-wrapper\
12+
automake-wrapper\
13+
libtool\
14+
git\
15+
#
16+
17+
bin/build_dependencies_unix.sh \
18+
--disable-fat\
19+
--use-gmp-github-mirror\
20+
--host aarch64-pc-windows-gnullvm\
21+
--patch-C23\
22+
--patch-ldd\
23+
#
24+
25+
PATH="$PATH:$(find "/c/Program Files/Microsoft Visual Studio/2022/" -name "HostARM64")/arm64/"
26+
27+
mkdir -p .local/lib
28+
cd .local/bin
29+
for dll_file in libgmp-*.dll libmpfr-*.dll libflint*.dll
30+
do
31+
lib_name=$(basename -s .dll ${dll_file})
32+
exports_file=${lib_name}-exports.txt
33+
def_file=${lib_name}.def
34+
lib_file=${lib_name}.lib
35+
name=$(echo ${lib_name}|sed 's/^lib//;s/[-.][0-9].*$//')
36+
37+
dumpbin //exports ${dll_file} > ${exports_file}
38+
39+
echo LIBRARY ${lib_name} > ${def_file}
40+
echo EXPORTS >> ${def_file}
41+
awk 'NR>19 && $4 != "" {print $4 " @"$1}' ${exports_file} >> ${def_file}
42+
sed -i 's/$/\r/' ${def_file}
43+
44+
lib //def:${def_file} //out:${lib_file} //machine:arm64
45+
rm ${exports_file} ${def_file} ${lib_name}.exp
46+
mv ${lib_file} ../lib/${name}.lib
47+
done
48+
cd ../..
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
diff --git a/Makefile.in b/Makefile.in
2+
index 0f25aa2b5..f6f46b7d6 100644
3+
--- a/Makefile.in
4+
+++ b/Makefile.in
5+
@@ -416,18 +416,12 @@ endif
6+
ifneq ($(SHARED), 0)
7+
shared: $(FLINT_DIR)/$(FLINT_LIB_FULL)
8+
9+
-# The following is to avoid reaching the maximum length of command line
10+
-# arguments, mainly present on MinGW.
11+
-define xxx_merged_lobj_rule
12+
-$(BUILD_DIR)/$(1)_merged.lo: $($(1)_LOBJS) | $(BUILD_DIR)
13+
- @$(LD) -r $($(1)_LOBJS) -o $(BUILD_DIR)/$(1)_merged.lo
14+
-endef
15+
-$(foreach dir, $(DIRS), $(eval $(call xxx_merged_lobj_rule,$(dir))))
16+
-MERGED_LOBJS:=$(foreach dir, $(DIRS),$(BUILD_DIR)/$(dir)_merged.lo)
17+
+SHARED_LINK_RSP := $(BUILD_DIR)/libflint-shared.rsp
18+
19+
-$(FLINT_DIR)/$(FLINT_LIB_FULL): $(MERGED_LOBJS)
20+
+$(FLINT_DIR)/$(FLINT_LIB_FULL): $(LOBJS) | $(BUILD_DIR)
21+
@echo "Building $(FLINT_LIB_FULL)"
22+
- @$(CC) $(CFLAGS) -shared $(EXTRA_SHARED_FLAGS) $(MERGED_LOBJS) -o $(FLINT_LIB_FULL) $(LDFLAGS) $(LIBS)
23+
+ @: $(file >$(SHARED_LINK_RSP))$(foreach obj,$(LOBJS),$(file >>$(SHARED_LINK_RSP),$(obj)))
24+
+ @$(CC) $(CFLAGS) -shared $(EXTRA_SHARED_FLAGS) @$(SHARED_LINK_RSP) -o $(FLINT_LIB_FULL) $(LDFLAGS) $(LIBS)
25+
@$(RM_F) $(FLINT_LIB)
26+
@$(RM_F) $(FLINT_LIB_MAJOR)
27+
@$(LN_S) $(FLINT_LIB_FULL) $(FLINT_LIB)

doc/source/build.rst

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -352,21 +352,30 @@ builds on Windows using MSVC.
352352

353353
The `MSYS2 <https://www.msys2.org/>`_ project provides a Unix-like environment
354354
for Windows and a package manager that can be used to install the dependencies.
355-
The git repo for ``python-flint`` has a script `bin/cibw_before_all_windows.sh
356-
<https://github.com/flintlib/python-flint/blob/master/bin/cibw_before_all_windows.sh>`_
357-
that installs the dependencies under MSYS2 and builds ``GMP``, ``MPFR``,
358-
``FLINT``. This script is used for building the Windows binaries for PyPI. We
359-
use the ``UCRT64`` (``mingw-w64-ucrt-x86_64``) toolchain under MSYS2 to build
360-
``GMP``, ``MPFR`` and ``FLINT`` because it makes it possible to have a fat
361-
build of ``GMP``
362-
(``--enable-fat``) which bundles micro-architecture specific optimisations for
363-
``x86_64`` in a redistributable shared library. This is important for
364-
performance on modern ``x86_64`` CPUs and is not possible if building ``GMP``
365-
with MSVC. The Python extension modules themselves are then built with MSVC via
355+
The git repo for ``python-flint`` has scripts
356+
`bin/cibw_before_all_windows_amd64.sh
357+
<https://github.com/flintlib/python-flint/blob/master/bin/cibw_before_all_windows_amd64.sh>`_
358+
and `bin/cibw_before_all_windows_arm64.sh
359+
<https://github.com/flintlib/python-flint/blob/master/bin/cibw_before_all_windows_arm64.sh>`_
360+
that install the dependencies under MSYS2 and build ``GMP``, ``MPFR``,
361+
``FLINT``. These scripts are used for building the Windows binaries for PyPI.
362+
363+
For ``x86_64`` wheels we use the ``UCRT64`` (``mingw-w64-ucrt-x86_64``)
364+
toolchain under MSYS2 to build ``GMP``, ``MPFR`` and ``FLINT`` because it
365+
makes it possible to have a fat build of ``GMP`` (``--enable-fat``) which
366+
bundles micro-architecture specific optimisations for ``x86_64`` in a
367+
redistributable shared library. This is important for performance on modern
368+
``x86_64`` CPUs and is not possible if building ``GMP`` with MSVC.
369+
370+
For Windows ``arm64`` wheels we use the ``CLANGARM64`` MSYS2 toolchain instead.
371+
The ``GMP`` build there does not use ``--enable-fat`` and instead uses the
372+
generic build that works with that toolchain.
373+
374+
The Python extension modules themselves are then built with MSVC via
366375
``meson --vsenv`` while linking against the MSYS2-built ``GMP``, ``MPFR`` and
367376
``FLINT`` libraries through ``pkg-config``. This mixed-toolchain arrangement
368-
keeps the ``GMP`` fat build while using the standard Windows compiler for the
369-
extension modules.
377+
keeps the MSYS2 dependency builds while using the standard Windows compiler for
378+
the extension modules on both ``x86_64`` and ``arm64``.
370379

371380

372381
.. _non_standard_location:

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ files = ["src"]
9494
addopts = "--import-mode=importlib"
9595

9696
[tool.cibuildwheel]
97-
skip = "*-win32 *-manylinux_i686 *-manylinux_armv7l *-musllinux_*"
97+
skip = "*-win32 pp*-win_arm64 *-manylinux_i686 *-manylinux_armv7l *-musllinux_*"
9898

9999
enable = [
100100
# Uncomment this to test beta versions of CPython in CI (but comment out
@@ -154,7 +154,6 @@ repair-wheel-command = [
154154
]
155155

156156
[tool.cibuildwheel.windows]
157-
before-all = "C:\\msys64\\usr\\bin\\bash bin/cibw_before_all_windows.sh"
158157
before-build = "pip install wheel delvewheel"
159158
config-settings = {setup-args = ["--vsenv"], build-dir = "build"}
160159
repair-wheel-command = [

0 commit comments

Comments
 (0)