Skip to content

Commit f42e335

Browse files
committed
BLD: add the actions
1 parent 0ca0546 commit f42e335

File tree

12 files changed

+3275
-70
lines changed

12 files changed

+3275
-70
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Build Dependencies(Win-ARM64)
2+
description: "Setup LLVM for Win-ARM64 builds"
3+
4+
runs:
5+
using: "composite"
6+
steps:
7+
- name: Install LLVM with checksum verification
8+
shell: pwsh
9+
run: |
10+
Invoke-WebRequest https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.6/LLVM-20.1.6-woa64.exe -UseBasicParsing -OutFile LLVM-woa64.exe
11+
$expectedHash = "92f69a1134e32e54b07d51c6e24d9594852f6476f32c3d70471ae00fffc2d462"
12+
$fileHash = (Get-FileHash -Path "LLVM-woa64.exe" -Algorithm SHA256).Hash
13+
if ($fileHash -ne $expectedHash) {
14+
Write-Error "Checksum verification failed. The downloaded file may be corrupted or tampered with."
15+
exit 1
16+
}
17+
Start-Process -FilePath ".\LLVM-woa64.exe" -ArgumentList "/S" -Wait
18+
echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
19+
echo "CC=clang-cl" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
20+
echo "CXX=clang-cl" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
21+
echo "FC=flang-new" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
22+

.github/workflows/wheels.yml

Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
name: Publish sdist and wheels
2+
3+
env:
4+
# A tag or branch name or a commit hash for the scipy/scipy repo, for which
5+
# to build wheels. This is normally set to `main` in the main branch of this
6+
# repo, and to a tag name (e.g., `v2.3.2`) on a release branch.
7+
SOURCE_REF_TO_BUILD: main
8+
9+
on:
10+
schedule:
11+
# ┌───────────── minute (0 - 59)
12+
# │ ┌───────────── hour (0 - 23)
13+
# │ │ ┌───────────── day of the month (1 - 31)
14+
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
15+
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
16+
# │ │ │ │ │
17+
- cron: "9 9 * * MON"
18+
pull_request:
19+
branches:
20+
- main
21+
- maintenance/**
22+
push:
23+
branches:
24+
- main # FOR TESTING ONLY
25+
workflow_dispatch:
26+
inputs:
27+
environment:
28+
description: Which PyPI environment to upload to, if any
29+
required: true
30+
type: choice
31+
options: ["none", "testpypi", "pypi"]
32+
33+
concurrency:
34+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
35+
cancel-in-progress: true
36+
37+
permissions:
38+
contents: read # to fetch code (actions/checkout)
39+
40+
jobs:
41+
build_wheels:
42+
name: BLD > ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}-${{ matrix.buildplat[2] }}-${{ matrix.buildplat[3] }}
43+
runs-on: ${{ matrix.buildplat[0] }}
44+
strategy:
45+
# Ensure that a wheel builder finishes even if another fails
46+
fail-fast: false
47+
matrix:
48+
# Github Actions doesn't support pairing matrix values together, let's improvise
49+
# https://github.com/github/feedback/discussions/7835#discussioncomment-1769026
50+
buildplat:
51+
# should also be able to do multi-archs on a single entry, e.g.
52+
# [windows-2025, win*, "AMD64 x86"]. However, those two require a different compiler setup
53+
# so easier to separate out here.
54+
- [ubuntu-24.04, manylinux, x86_64, "", ""]
55+
- [ubuntu-24.04, musllinux, x86_64, "", ""]
56+
- [ubuntu-24.04-arm, manylinux, aarch64, "", ""]
57+
- [ubuntu-24.04-arm, musllinux, aarch64, "", ""]
58+
- [macos-13, macosx, x86_64, openblas, "10.14"]
59+
- [macos-15-intel, macosx, x86_64, accelerate, "14.0"]
60+
- [macos-14, macosx, arm64, openblas, "12.3"]
61+
- [macos-14, macosx, arm64, accelerate, "14.0"]
62+
- [windows-2025, win, AMD64, "", ""]
63+
- [windows-11-arm, win, ARM64, "", ""]
64+
python: [["cp311", "3.11"], ["cp312", "3.12"], ["cp313", "3.13"], ["cp313t", "3.13"], ["cp314", "cp314"], ["cp314t", "cp314"]]
65+
# python[0] is used to specify the python versions made by cibuildwheel
66+
67+
steps:
68+
- name: Checkout scipy-release
69+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
70+
with:
71+
persist-credentials: false
72+
73+
- name: Checkout scipy
74+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
75+
with:
76+
repository: scipy/scipy
77+
ref: ${{ env.SOURCE_REF_TO_BUILD }}
78+
path: scipy-src
79+
submodules: true
80+
persist-credentials: false
81+
82+
# the version of python we'll run cibuildwheel with
83+
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
84+
with:
85+
python-version: 3.13
86+
87+
- name: win_amd64 - install rtools
88+
if: ${{ matrix.buildplat[1] == 'win' && matrix.buildplat[2] == 'AMD64' }}
89+
run: |
90+
# mingw-w64
91+
choco install rtools -y --no-progress --force --version=4.0.0.20220206
92+
echo "c:\rtools40\ucrt64\bin;" >> $env:GITHUB_PATH
93+
94+
- name: Set environment variables for ARM64
95+
if: matrix.buildplat[1] == 'win' && matrix.buildplat[2] == 'ARM64'
96+
run: |
97+
echo "CC=clang-cl" >> $env:GITHUB_ENV
98+
echo "CXX=clang-cl" >> $env:GITHUB_ENV
99+
echo "FC=flang" >> $env:GITHUB_ENV
100+
echo "TARGET_ARCH=${{ matrix.buildplat[2] }}" >> $env:GITHUB_ENV
101+
102+
- name: Set up Flang and pkgconf for ARM64
103+
if: matrix.buildplat[1] == 'win' && matrix.buildplat[2] == 'ARM64'
104+
uses: ./.github/windows_arm64_steps
105+
106+
- name: pkg-config-for-win
107+
if: runner.os == 'windows'
108+
run: |
109+
choco install -y --no-progress --stoponfirstfailure --checksum 6004DF17818F5A6DBF19CB335CC92702 pkgconfiglite
110+
$CIBW = "${{ github.workspace }}/.openblas"
111+
# pkgconfig needs a complete path, and not just "./openblas since the
112+
# build is run in a tmp dir (?)
113+
# It seems somewhere in the env passing, `\` is not
114+
# passed through, so convert it to '/'
115+
$CIBW = $CIBW.replace("\","/")
116+
echo "CIBW_ENVIRONMENT_WINDOWS=PKG_CONFIG_PATH=$CIBW" >> $env:GITHUB_ENV
117+
118+
# the macOS matrix is complicated.
119+
# - arm64, accelerate, >=14.0
120+
# The easiest of them all (sort of). However, if you wish to target 14 you
121+
# can only build on macos-14 with the system compiler. If you try building on
122+
# macos-15 there are libraries with a minimum target of 15. Presumably when
123+
# the macos-14 is dropped we'll need to customise the compiler a bit.
124+
# In addition, we can't use Accelerate for < 14 because the library had bugs.
125+
# This means OpenBLAS has to be used.
126+
# - x86_64, accelerate, >=14.0
127+
# Complicated because x86_64 is only available on the macos-15-intel image.
128+
# - x86_64, openblas, "10.14"
129+
# Complicated because x86_64 is only available on the macos-15-intel image.
130+
# Needs an older compiler.
131+
# - arm64, openblas, "12.3"
132+
# Complicated because MACOS_DEPLOYMENT_TARGET has to be set to 12.3 (there's
133+
# some reason why we don't support <12.3), which results in 12_3 in the wheel
134+
# name. This is illegal, so we have to change the wheel name to 12_0 after
135+
# the build.
136+
# OpenBLAS is also complicated because the `delocate` step tries
137+
# to copy two libgfortran libraries into the wheel, and falls over. This
138+
# necessitates using install_name_tool on the scipy_openblas32 dylibs.
139+
# The libraries are also built with an older version of gfortran (11), which
140+
# requires installation of that version. Whilst this version is available
141+
# from homebrew, it doesn't come with an old enough deployment target.
142+
# We therefore have to jump through hoops to install a community packaged
143+
# compiler.
144+
- name: Setup macOS
145+
if: startsWith( matrix.buildplat[0], 'macos-' )
146+
run: |
147+
if [[ ${{ matrix.buildplat[3] }} == 'accelerate' ]]; then
148+
echo CIBW_CONFIG_SETTINGS=\"setup-args=-Dblas=accelerate\" >> "$GITHUB_ENV"
149+
150+
# use preinstalled gfortran for Accelerate builds
151+
ln -s $(which gfortran-13) gfortran
152+
export PATH=$PWD:$PATH
153+
echo "PATH=$PATH" >> "$GITHUB_ENV"
154+
155+
# Builds with Accelerate only target macOS>=14.0
156+
CIBW_ENV="CIBW_ENVIRONMENT_MACOS=MACOSX_DEPLOYMENT_TARGET=14.0 INSTALL_OPENBLAS=false"
157+
else
158+
# use conda-forge compilers the difficult targets
159+
INSTALL_DIR=/Users/runner/miniforge3
160+
161+
wget -q -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"
162+
163+
# Make the installer executable
164+
chmod +x Miniforge3.sh
165+
166+
# Run the installer in batch mode (-b) and specify the installation prefix (-p)
167+
# The -u flag is for updating an existing installation if it exists
168+
./Miniforge3.sh -b -u -p "${INSTALL_DIR}"
169+
170+
source "${INSTALL_DIR}/etc/profile.d/conda.sh"
171+
conda init
172+
conda create -q -y -n build compilers
173+
echo "conda activate build" >> $HOME/.bash_profile
174+
cat $HOME/.bash_profile
175+
176+
CIBW_ENV="CIBW_ENVIRONMENT_MACOS=PKG_CONFIG_PATH=$PWD/.openblas \
177+
MACOSX_DEPLOYMENT_TARGET=${{ matrix.buildplat[4] }}"
178+
fi
179+
echo "$CIBW_ENV" >> $GITHUB_ENV
180+
181+
PREFIX=DYLD_LIBRARY_PATH="\$(dirname \$(gfortran --print-file-name libgfortran.dylib))"
182+
CIBW="$PREFIX delocate-wheel -v $EXCLUDE --require-archs {delocate_archs} -w {dest_dir} {wheel}"
183+
echo "CIBW_REPAIR_WHEEL_COMMAND_MACOS=$CIBW" >> $GITHUB_ENV
184+
185+
- name: Build Wheels
186+
shell: bash -el {0}
187+
run: |
188+
pip install cibuildwheel
189+
export CIBW_BUILD=${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}*
190+
export CIBW_ARCHS=${{ matrix.buildplat[2] }}
191+
export CIBW_ENABLE="cpython-freethreading cpython-prerelease"
192+
cibuildwheel --output-dir=dist --config-file=cibuildwheel.toml scipy-src
193+
194+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
195+
with:
196+
path: ./dist/*.whl
197+
name: ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}-${{ matrix.buildplat[2] }}-${{ matrix.buildplat[3] }}-${{ matrix.buildplat[4] }}
198+
199+
# We upload nightlies only on cron job runs, so it doesn't overlap with
200+
# builds from which we publish to PyPI - we don't want these extra
201+
# dependencies when building release artifacts.
202+
- name: install micromamba
203+
# win-arm64 is unsupported by micromamba at the moment
204+
if: github.event_name == 'schedule' && matrix.buildplat[1] != 'win_arm64'
205+
uses: mamba-org/setup-micromamba@b09ef9b599704322748535812ca03efb2625677b # v2.0.5
206+
with:
207+
# For installation of anaconda-client, required for upload to anaconda.org
208+
init-shell: bash
209+
environment-name: upload-env
210+
create-args: >-
211+
anaconda-client
212+
213+
- name: win-arm64 install anaconda client
214+
if: github.event_name == 'schedule' && matrix.buildplat[1] == 'win_arm64'
215+
run: |
216+
# Rust installation needed for rpds-py.
217+
Invoke-WebRequest https://static.rust-lang.org/rustup/dist/aarch64-pc-windows-msvc/rustup-init.exe -UseBasicParsing -Outfile rustup-init.exe
218+
.\rustup-init.exe -y
219+
$env:PATH="$env:PATH;$env:USERPROFILE\.cargo\bin"
220+
pip install anaconda-client
221+
222+
- name: Upload to anaconda.org
223+
if: github.event_name == 'schedule' && github.repository == 'scipy/scipy-release'
224+
shell: bash -el {0} # required for micromamba
225+
env:
226+
TOKEN: ${{ secrets.scipy_NIGHTLY_UPLOAD_TOKEN }}
227+
run: |
228+
anaconda -q -t ${TOKEN} upload --force -u scientific-python-nightly-wheels ./dist/*.whl
229+
230+
# -------------------------------------------------------------------------------------
231+
build_sdist:
232+
name: Build sdist
233+
runs-on: ubuntu-latest
234+
if: github.repository == 'andyfaff/scipy'
235+
236+
steps:
237+
- name: Checkout scipy
238+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
239+
with:
240+
repository: scipy/scipy
241+
submodules: true
242+
ref: ${{ env.SOURCE_REF_TO_BUILD }}
243+
persist-credentials: false
244+
245+
- name: Build sdist
246+
run: |
247+
python -m pip install -U pip build
248+
249+
# need openblas even for the sdist build
250+
OPENBLAS=openblas32
251+
pkgconf_path=$GITHUB_WORKSPACE/.openblas
252+
253+
rm -rf $pkgconf_path
254+
mkdir -p $pkgconf_path
255+
256+
python -m pip install -r $GITHUB_WORKSPACE/requirements/openblas.txt
257+
python -c "import scipy_${OPENBLAS}; print(scipy_${OPENBLAS}.get_pkg_config())" > $pkgconf_path/scipy-openblas.pc
258+
export PKG_CONFIG_PATH=$pkgconf_path
259+
echo "PKG_CONFIG_PATH=$pkgconf_path" >> "$GITHUB_ENV"
260+
261+
python -m build --sdist
262+
263+
- name: Test the sdist
264+
run: |
265+
python -m pip install -v dist/*.gz
266+
pip install -r $GITHUB_WORKSPACE/requirements/test.txt
267+
cd .. # Can't import scipy within scipy src directory
268+
python -c "import scipy, sys; print(scipy.__version__); sys.exit(scipy.test() is False)"
269+
270+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
271+
with:
272+
name: sdist
273+
path: ./dist/*
274+
275+
# -------------------------------------------------------------------------------------
276+
testpypi-publish:
277+
name: Publish release to TestPyPI
278+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'testpypi'
279+
needs: [build_wheels, build_sdist]
280+
runs-on: ubuntu-latest
281+
environment:
282+
name: testpypi
283+
url: https://test.pypi.org/p/scipy
284+
permissions:
285+
id-token: write # mandatory for trusted publishing
286+
steps:
287+
- name: Download sdist and wheels
288+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
289+
with:
290+
path: dist
291+
merge-multiple: true
292+
293+
- name: Publish
294+
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
295+
with:
296+
repository-url: https://test.pypi.org/legacy/
297+
skip-existing: true
298+
print-hash: true
299+
attestations: true
300+
301+
# -------------------------------------------------------------------------------------
302+
check_version:
303+
name: Ensure commit is tag before upload to PyPi
304+
305+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'pypi'
306+
needs: [build_wheels, build_sdist]
307+
runs-on: ubuntu-latest
308+
steps:
309+
- name: Checkout scipy
310+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
311+
with:
312+
repository: scipy/scipy
313+
ref: ${{ env.SOURCE_REF_TO_BUILD }}
314+
path: scipy-src
315+
fetch-depth: 0
316+
fetch-tags: true
317+
submodules: false
318+
persist-credentials: false
319+
320+
- name: Examine git commit
321+
run: |
322+
cd scipy-src
323+
hash=$(git describe HEAD)
324+
echo $hash
325+
if [[ $hash == *"-"*"-"* ]]; then
326+
echo "SOURCE_REF_TO_BUILD is not a tag"
327+
exit 1
328+
else
329+
echo "SOURCE_REF_TO_BUILD is a tag"
330+
fi;
331+
332+
# -------------------------------------------------------------------------------------
333+
pypi-publish:
334+
name: Publish release to PyPI
335+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'pypi'
336+
needs: [check_version]
337+
runs-on: ubuntu-latest
338+
environment:
339+
name: pypi
340+
url: https://pypi.org/p/scipy
341+
permissions:
342+
id-token: write # mandatory for trusted publishing
343+
steps:
344+
- name: Download sdist and wheels
345+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
346+
with:
347+
path: dist
348+
merge-multiple: true
349+
350+
- name: Publish
351+
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
352+
with:
353+
print-hash: true
354+
attestations: true

0 commit comments

Comments
 (0)