Skip to content

Commit c026625

Browse files
committed
Build wheels on windows
1 parent 589740a commit c026625

File tree

4 files changed

+92
-5
lines changed

4 files changed

+92
-5
lines changed

.github/workflows/wheels.yml

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,52 @@ jobs:
6565
name: osx-wheel-${{ matrix.os }}-${{ matrix.python }}
6666
path: dist
6767

68+
Windows:
69+
name: Build Windows - ${{ matrix.python }}
70+
runs-on: windows-latest
71+
strategy:
72+
matrix:
73+
python: [3.9, "3.10", 3.11, 3.12, 3.13]
74+
arch: [x64]
75+
steps:
76+
- name: Checkout
77+
uses: actions/checkout@v4.2.2
78+
with:
79+
submodules: true
80+
- name: Set up Python ${{ matrix.python }}
81+
uses: actions/setup-python@v5.4.0
82+
with:
83+
python-version: ${{ matrix.python }}
84+
architecture: ${{ matrix.arch }}
85+
- name: Install GSL via vcpkg
86+
run: |
87+
vcpkg install gsl:${{ matrix.arch }}-windows
88+
shell: cmd
89+
- name: Install deps
90+
run: |
91+
pip install --upgrade pip build delvewheel
92+
- name: Fix windows symlinks
93+
run: |
94+
if (Test-Path "lwt_interface") { Remove-Item -Recurse -Force "lwt_interface" }
95+
Copy-Item -Recurse "git-submodules/tskit/python/lwt_interface" "./lwt_interface"
96+
shell: powershell
97+
- name: Build Wheel
98+
run: |
99+
python -m build --wheel
100+
- name: Bundle dynamic libs
101+
run: |
102+
$vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT
103+
if (-not $vcpkgRoot) { $vcpkgRoot = "C:\vcpkg" }
104+
$gslBinPath = Join-Path $vcpkgRoot "installed\x64-windows\bin"
105+
$env:PATH = "$gslBinPath;$env:PATH"
106+
delvewheel repair dist/*.whl -w dist/ --add-path "$gslBinPath"
107+
shell: powershell
108+
- name: Upload Wheels
109+
uses: actions/upload-artifact@v4.6.1
110+
with:
111+
name: win-wheel-${{ matrix.python }}
112+
path: dist
113+
68114
manylinux:
69115
runs-on: ubuntu-24.04
70116
steps:
@@ -153,10 +199,35 @@ jobs:
153199
tskit provenances tmp.trees
154200
155201
202+
Windows-test:
203+
runs-on: windows-latest
204+
needs: ['Windows']
205+
strategy:
206+
matrix:
207+
python: [3.9, "3.10", 3.11, 3.12, 3.13]
208+
steps:
209+
- name: Download wheels
210+
uses: actions/download-artifact@v4.2.0
211+
with:
212+
name: win-wheel-${{ matrix.python }}
213+
- name: Set up Python ${{ matrix.python }}
214+
uses: actions/setup-python@v5.4.0
215+
with:
216+
python-version: ${{ matrix.python }}
217+
- name: Install wheel and test
218+
run: |
219+
python -VV
220+
pip install numpy newick>=1.3.0 tskit>=0.5.2 demes>=0.2
221+
pip install msprime --no-index --only-binary msprime -f .
222+
python -c "import msprime"
223+
msp simulate 10 tmp.trees
224+
tskit info tmp.trees
225+
tskit provenances tmp.trees
226+
156227
PyPI_Upload:
157228
runs-on: ubuntu-24.04
158229
environment: release
159-
needs: ['OSX-test', 'manylinux-test']
230+
needs: ['OSX-test', 'manylinux-test', 'Windows-test']
160231
permissions:
161232
id-token: write
162233
steps:
@@ -166,6 +237,8 @@ jobs:
166237
run: |
167238
mkdir dist
168239
cp */*.{whl,gz} dist/.
240+
# Windows wheels have different naming pattern
241+
if [ -d "win-wheel"* ]; then cp win-wheel*/*.whl dist/. || true; fi
169242
- name: Publish distribution to Test PyPI
170243
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
171244
uses: pypa/gh-action-pypi-publish@v1.12.4

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
- Add support and wheels for Python3.13
1212

13+
- Add wheels on Windows ({pr}`2414`, {issue}`2200`,{user}`benjeffery`)
14+
1315
**Breaking changes**:
1416

1517
- The `.asdict()` methods for Demography, Population, and Event classes in the

docs/installation.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,6 @@ more details on managing packages and environments.
119119
Installing using `pip` is more flexible than `conda` as it
120120
can support more versions of Python and dependencies can be customised.
121121

122-
```{warning}
123-
Pip installations are not supported on Windows due to our dependency on GSL.
124-
```
125-
126122
:::{warning}
127123

128124
If you installed Python using anaconda/miniconda, please install

setup.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ def _run_command(self, args):
3838
return subprocess.check_output(args, text=True)
3939

4040
def _configure_gsl(self):
41+
# Try vcpkg on Windows first
42+
if IS_WINDOWS:
43+
vcpkg_root = os.getenv("VCPKG_ROOT")
44+
if vcpkg_root is None:
45+
vcpkg_root = os.getenv("VCPKG_INSTALLATION_ROOT")
46+
if vcpkg_root and os.path.exists(vcpkg_root):
47+
gsl_include = os.path.join(
48+
vcpkg_root, "installed", "x64-windows", "include"
49+
)
50+
gsl_lib = os.path.join(vcpkg_root, "installed", "x64-windows", "lib")
51+
if os.path.exists(gsl_include) and os.path.exists(gsl_lib):
52+
self.include_dirs.append(gsl_include)
53+
self.library_dirs.append(gsl_lib)
54+
return
55+
56+
# Fallback to gsl-config on Unix-like systems
4157
output = self._run_command(["gsl-config", "--cflags"]).split()
4258
if len(output) > 0:
4359
token = output[0]

0 commit comments

Comments
 (0)