Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions .github/workflows/build.yml

This file was deleted.

195 changes: 195 additions & 0 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
name: Build wheels

on:
push:
branches: [master, main, beta]
tags: ['*']
pull_request:
workflow_dispatch:
inputs:
publish:
description: "Publish wheels to PyPI after building"
type: boolean
default: false
test_release:
description: "When publishing, rewrite the package name to assimulo-testing (fork-only; remove before merging upstream)"
type: boolean
default: false

permissions:
contents: read

jobs:
# Picks a small matrix for PRs and a full matrix for everything else.
# The `matrix` context is not available in `jobs.<id>.if`, so the
# row selection cannot be done inline on the build jobs.
config:
name: Resolve matrix
runs-on: ubuntu-latest
outputs:
linux: ${{ steps.set.outputs.linux }}
windows: ${{ steps.set.outputs.windows }}
steps:
- id: set
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "pull_request" ]; then
LINUX='[
{"arch":"x86_64","runner":"ubuntu-latest","python":"cp311"},
{"arch":"x86_64","runner":"ubuntu-latest","python":"cp314"}
]'
WINDOWS='[
{"arch":"amd64","python":"cp311"},
{"arch":"amd64","python":"cp314"}
]'
else
LINUX='[
{"arch":"x86_64", "runner":"ubuntu-latest", "python":"cp311"},
{"arch":"x86_64", "runner":"ubuntu-latest", "python":"cp312"},
{"arch":"x86_64", "runner":"ubuntu-latest", "python":"cp313"},
{"arch":"x86_64", "runner":"ubuntu-latest", "python":"cp314"},
{"arch":"aarch64","runner":"ubuntu-22.04-arm","python":"cp311"},
{"arch":"aarch64","runner":"ubuntu-22.04-arm","python":"cp312"},
{"arch":"aarch64","runner":"ubuntu-22.04-arm","python":"cp313"},
{"arch":"aarch64","runner":"ubuntu-22.04-arm","python":"cp314"}
]'
WINDOWS='[
{"arch":"amd64","python":"cp311"},
{"arch":"amd64","python":"cp312"},
{"arch":"amd64","python":"cp313"},
{"arch":"amd64","python":"cp314"}
]'
fi
{
echo "linux<<EOF"
echo "$LINUX"
echo "EOF"
echo "windows<<EOF"
echo "$WINDOWS"
echo "EOF"
} >> "$GITHUB_OUTPUT"

linux:
name: Linux ${{ matrix.arch }} (${{ matrix.python }})
needs: config
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.config.outputs.linux) }}
steps:
- uses: actions/checkout@v4

- name: Rewrite package name to assimulo-testing
if: github.event_name == 'workflow_dispatch' && inputs.publish && inputs.test_release
run: |
sed -i 's/^name = "Assimulo"$/name = "assimulo-testing"/' pyproject.toml
sed -i "s/^ 'Assimulo',$/ 'assimulo-testing',/" meson.build
grep '^name = ' pyproject.toml
grep -n "assimulo-testing" meson.build

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- run: pip install cibuildwheel

- name: Build manylinux image (SuperLU + SUNDIALS pre-installed)
run: docker build --build-arg ARCH=${{ matrix.arch }} -f Dockerfile.manylinux -t assimulo-manylinux .

- name: Build wheel
env:
CIBW_BUILD: "${{ matrix.python }}-*"
run: cibuildwheel --platform linux --output-dir dist/

- uses: actions/upload-artifact@v4
with:
name: wheels-linux-${{ matrix.arch }}-${{ matrix.python }}
path: dist/*.whl

windows:
name: Windows ${{ matrix.arch }} (${{ matrix.python }})
needs: config
runs-on: windows-2022
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.config.outputs.windows) }}
steps:
- uses: actions/checkout@v4

- name: Rewrite package name to assimulo-testing
if: github.event_name == 'workflow_dispatch' && inputs.publish && inputs.test_release
shell: bash
run: |
sed -i 's/^name = "Assimulo"$/name = "assimulo-testing"/' pyproject.toml
sed -i "s/^ 'Assimulo',$/ 'assimulo-testing',/" meson.build
grep '^name = ' pyproject.toml
grep -n "assimulo-testing" meson.build

- name: Set up MSYS2 UCRT64
uses: msys2/setup-msys2@v2
with:
msystem: UCRT64
update: true
install: >-
git
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-gcc-fortran
mingw-w64-ucrt-x86_64-cmake
mingw-w64-ucrt-x86_64-ninja
mingw-w64-ucrt-x86_64-pkg-config

- name: Build SUNDIALS
shell: msys2 {0}
run: bash tools/wheels/build_dependencies_windows.sh

# Add UCRT64 and SUNDIALS to PATH so cibuildwheel/meson find gcc and DLLs.
# Set CC/CXX/FC so meson uses MSYS2 GCC instead of MSVC.
- name: Configure compiler environment
shell: pwsh
run: |
echo "C:\msys64\ucrt64\bin" | Out-File -FilePath $env:GITHUB_PATH -Append
echo "C:\deps\bin" | Out-File -FilePath $env:GITHUB_PATH -Append
echo "CC=gcc" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "CXX=g++" | Out-File -FilePath $env:GITHUB_ENV -Append
echo "FC=gfortran" | Out-File -FilePath $env:GITHUB_ENV -Append

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- run: pip install cibuildwheel
shell: pwsh

- name: Build wheel
shell: pwsh
env:
CIBW_BUILD: "${{ matrix.python }}-*"
run: cibuildwheel --platform windows --output-dir dist/

- uses: actions/upload-artifact@v4
with:
name: wheels-windows-${{ matrix.arch }}-${{ matrix.python }}
path: dist/*.whl

upload_pypi:
name: Upload to PyPI
needs: [linux, windows]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' && inputs.publish && startsWith(github.ref, 'refs/tags/v')
environment:
name: pypi
url: https://pypi.org/p/Assimulo
permissions:
id-token: write # required for OIDC Trusted Publisher
steps:
- uses: actions/download-artifact@v4
with:
pattern: wheels-*
path: dist/
merge-multiple: true

- uses: pypa/gh-action-pypi-publish@release/v1
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
build.sh
build/
dist/
*.pyc
.venv
.env
50 changes: 50 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,4 +1,54 @@
--- CHANGELOG ---
--- Assimulo-3.9.0b2 ---
Second beta of the modernized build system. No functional or API changes
relative to 3.9.0b1.

Packaging and distribution:
* Wheel matrix expanded to CPython 3.14 and Linux aarch64
(ubuntu-22.04-arm runners). Pull requests build cp311 + cp314 on
Linux x86_64 and Windows; master/tag/workflow_dispatch builds the
full matrix.
* wheels.yml restructured: a `config` job emits the matrix as JSON and
the linux/windows jobs consume it via fromJSON, working around the
fact that the `matrix` context is not available in `jobs.<id>.if`.

Tests:
* Replaced the non-idiomatic `@classmethod` + `@pytest.fixture(autouse=True)`
stack on `setup_class` with the documented `setup_method` xunit hook.
The previous pattern crashed pytest on CPython 3.14
(`AttributeError: 'FixtureFunctionDefinition' object has no attribute
'__code__'`); `setup_method` runs cleanly on every supported CPython.

--- Assimulo-3.9.0b1 ---
Beta release of the modernized build system. No functional or API changes
relative to 3.8.0.

Build system:
* Switched from distutils/setup.py to meson-python (PEP 517 build backend).
* Bumped minimum requirements: Python >= 3.11, NumPy >= 2.1, SciPy >= 1.14,
Cython >= 3.0.7.
* Build configuration is now declared in pyproject.toml + meson.build +
meson.options.
* Fortran solvers (Radau5, Dopri5, Rodas, Odassl, Odepack, Dasp3, Glimda,
Kvaernoe) are now wrapped via numpy.f2py invoked from meson; the previous
f2py glue has been replaced by tools/f2py_wrapper.py.
* SUNDIALS is sourced from the Modelon SUNDIALS fork as the canonical
dependency; CVode and IDA are statically linked into the wrapper modules
by default.
* BLAS/LAPACK unified to dynamic OpenBLAS on both Linux and Windows.
* SuperLU support enabled on Windows wheels.
* Examples directory moved under src/assimulo for consistency with the
installed package layout.

Packaging and distribution:
* Added manylinux and Windows wheel builds via cibuildwheel.
* Added GitHub Actions workflow (.github/workflows/wheels.yml) for building
and publishing wheels to PyPI via a Trusted Publisher.
* Added Docker images for reproducible local builds (Dockerfile,
Dockerfile.manylinux) and a Makefile target for incremental development
builds.
* Added RELEASING.md describing the manual release procedure.

--- Assimulo-3.8.0---
* Enabled interpolated output support for ExplicitEuler and ImplicitEuler.

Expand Down
10 changes: 8 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ Python/Cython library providing a unified interface to ODE and DAE solvers. Solv

## Build

Build backend is `meson-python`; options in `meson.options`. All targets run inside Docker.

```
make build
make build # full install into .venv
make build-dev # incremental editable install (keeps builddir/)
make check-meson.build # validate meson config without building
```

Runs inside Docker (builds a dev image if needed). Dependencies: Python ≥ 3.9, NumPy ≥ 1.19.5, SciPy ≥ 1.10.1, Cython ≥ 3.0.7, SUNDIALS v2.7.0.
Dependencies: Python ≥ 3.11, NumPy ≥ 2.1, SciPy ≥ 1.14, Cython ≥ 3.0.7, SUNDIALS v2.7.0. Linux requires `libopenblas-dev`; Windows links BLAS statically.

Fortran solvers are wrapped via `tools/f2py_wrapper.py` (generates C glue from `.pyf` files).

## Testing

Expand Down
Loading
Loading