Skip to content
Open
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
64 changes: 25 additions & 39 deletions .github/workflows/deploy-on-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -275,29 +275,28 @@ jobs:
wheels:
needs: setup-jobs
if: needs.setup-jobs.outputs.allowed-jobs == 'Wheels' || needs.setup-jobs.outputs.allowed-jobs == 'All'
name: ${{ matrix.name }} ${{ matrix.py }} wheel
name: ${{ matrix.name }} Stable ABI wheel

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not include the Python version anymore?

@hsorby hsorby Sep 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is becuase with the stable ABI we don’t need individual Python versions, we build against the stable ABI and it will work for all versions that don’t break our baseline stable ABI we use, which is Python 3.10.

runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-15, ubuntu-24.04, ubuntu-24.04-arm, windows-2025-vs2026, windows-11-arm]
py: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
os: [macos-15, macos-15-intel, ubuntu-24.04, ubuntu-24.04-arm, windows-2025-vs2026, windows-11-arm]
py: ['3.14']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only Python 3.14? What about Python 3.15 and probably even Python 3.13 (at least)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one needed now becuase we build with Python 3.14 but it will fit all Python versions from 3.10 upwards.

include:
- name: 'Windows'
os: windows-2025-vs2026
- name: 'Windows ARM'
os: windows-11-arm
- name: 'Linux'
- name: 'LinuxARM'
os: ubuntu-24.04-arm
- name: 'Linux ARM'
- name: 'LinuxIntel'
os: ubuntu-24.04
- name: 'macOS'
- name: 'macOSARM'
os: macos-15
exclude:
- os: ubuntu-24.04
py: '3.9'
- os: ubuntu-24.04-arm
py: '3.9'
- name: 'macOSIntel'
os: macos-15-intel
- name: 'WindowsARM'
os: windows-11-arm
arch: arm64
- name: 'WindowsIntel'
os: windows-2025-vs2026
arch: amd64

steps:
- name: Check out libCellML
Expand All @@ -309,57 +308,44 @@ jobs:
id: setup
shell: bash
run: |
VERSION="${GITHUB_REF_NAME_TMP#refs/tags/v}"
if [[ "$OSTYPE" == "darwin*" ]]; then
VERSION="${GITHUB_REF#refs/tags/v}"
echo "Setting version as: VERSION=${VERSION}"
if [[ "$OSTYPE" == darwin* ]]; then
sed -i '' "s/__VERSION__/${VERSION}/" src/bindings/python/pyproject.toml
else
sed -i "s/__VERSION__/${VERSION}/" src/bindings/python/pyproject.toml
fi
grep '^version' src/bindings/python/pyproject.toml

v=${{ matrix.py }}
echo "Setting tag as: tag=${GITHUB_REF#refs/tags/}"
echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
echo "Setting build as: build=cp${v/./}-*"
echo "build=cp${v/./}-*" >> $GITHUB_OUTPUT
if [[ "macOS" == "${{ matrix.name }}" ]]; then
echo "Setting macos_archs as: macos_archs='x86_64 arm64'"
echo "macos_archs=x86_64 arm64" >> $GITHUB_OUTPUT
echo "macos_deployment_target=14.0" >> $GITHUB_OUTPUT
elif [[ "Windows" == "${{ matrix.name }}" ]]; then
echo "Setting win_arch as: win_arch=amd64"
echo "win_arch=amd64" >> $GITHUB_OUTPUT
elif [[ "Windows ARM" == "${{ matrix.name }}" ]]; then
echo "Setting win_arch as: win_arch=arm64"
echo "win_arch=arm64" >> $GITHUB_OUTPUT
fi

- name: Configure MSVC (Windows)
if: runner.os == 'Windows'
uses: TheMrMilchmann/setup-msvc-dev@v4
with:
arch: ${{ steps.setup.outputs.win_arch }}
arch: ${{ matrix.arch }}

- name: Install SWIG (macOS)
if: runner.os == 'macOS'
run: brew install swig

- name: Build wheels
uses: pypa/cibuildwheel@v3.4
uses: pypa/cibuildwheel@v4.2
env:
#CIBW_BUILD_VERBOSITY: 1
CIBW_ARCHS: auto64
CIBW_ARCHS_MACOS: ${{ steps.setup.outputs.macos_archs }}
CIBW_BUILD: ${{ steps.setup.outputs.build }}
CIBW_TEST_SKIP: "*_arm64"
CIBW_BEFORE_ALL_LINUX: yum install -y libxml2-devel || (apk add libxml2-dev && rm /usr/lib/cmake/libxml2/libxml2-config.cmake)
CIBW_ENVIRONMENT: >
LIBCELLML_VERSION_TAG=${{ steps.setup.outputs.tag }}
MACOSX_DEPLOYMENT_TARGET=${{ steps.setup.outputs.macos_deployment_target }}
CIBW_REPAIR_WHEEL_COMMAND_MACOS: ""
LIBCELLML_VERSION_TAG=${{ github.event.release.tag_name }}
MACOSX_DEPLOYMENT_TARGET=14.0
CIBW_BEFORE_BUILD_LINUX: pip install renamewheel
CIBW_BEFORE_BUILD_WINDOWS: cd src/bindings/python && cmake -S wheel_dependencies -B build-wheel_dependencies -G Ninja && cd build-wheel_dependencies && ninja
CIBW_REPAIR_WHEEL_COMMAND_LINUX: renamewheel -w {dest_dir} {wheel}
CIBW_REPAIR_WHEEL_COMMAND_MACOS: ""
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: ""
with:
output-dir: wheelhouse
package-dir: src/bindings/python/
Expand All @@ -368,13 +354,13 @@ jobs:
uses: actions/upload-artifact@v7
with:
path: ./wheelhouse/*.whl
name: ${{ matrix.name }}-${{ matrix.py }}-wheel
name: ${{ matrix.name }}-wheel
retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}

publish-wheels:
if: needs.setup-jobs.outputs.binaries-destination == 'Publish'
needs: wheels
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
timeout-minutes: 5 # Docker+network are slow sometimes.
permissions:
id-token: write
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.18.0)
cmake_minimum_required(VERSION 3.26.0)

if(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET 14.0 CACHE STRING "Minimum OS X deployment version.")
Expand Down
13 changes: 11 additions & 2 deletions cmake/environmentchecks.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,16 @@ else ()

test_undefined_symbols_allowed()

find_package(Python ${PREFERRED_PYTHON_VERSION} COMPONENTS Interpreter ${_FIND_PYTHON_DEVELOPMENT_TYPE})
find_package(Python ${PREFERRED_PYTHON_VERSION} COMPONENTS Interpreter Development.SABIModule Development.Module)

if (TARGET Python::SABIModule)
set(_PYTHON_LINK_TARGET Python::SABIModule)
elseif (TARGET Python::Module)
message(STATUS "Using backup Python::Module target for linking.")
set(_PYTHON_LINK_TARGET Python::Module)
else()
message(STATUS "Could not find Python::SABIModule or Python::Module target.")
endif()

find_program(BUILDCACHE_EXE buildcache)
if(NOT BUILDCACHE_EXE)
Expand Down Expand Up @@ -152,7 +161,7 @@ if(SWIG_EXECUTABLE)
set(BINDINGS_AVAILABLE TRUE CACHE INTERNAL "Executable required to generate bindings is available.")
endif()

if(BINDINGS_AVAILABLE AND (Python_Development.Module_FOUND OR Python_Development_FOUND))
if(BINDINGS_AVAILABLE AND (Python_Development.SABIModule_FOUND OR Python_Development.Module_FOUND))
set(PYTHON_BINDINGS_AVAILABLE TRUE CACHE INTERNAL "Requirements for creating Python bindings are available.")
endif()

Expand Down
7 changes: 1 addition & 6 deletions src/bindings/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,12 @@ foreach(SWIG_INTERFACE_SRC ${SWIG_INTERFACE_SRCS})
SOURCES ${SWIG_INTERFACE_SRC}
)
target_link_libraries(${MODULE_TARGET} PRIVATE cellml)
target_compile_definitions(${MODULE_TARGET} PRIVATE Py_LIMITED_API=0x030a0000)

if(SWIG_VERSION VERSION_GREATER_EQUAL 4.1.0)
set_target_properties(${MODULE_TARGET} PROPERTIES SWIG_COMPILE_OPTIONS -flatstaticmethod)
endif()

if(FIND_PYTHON_DEVELOPMENT_MODULE)
set(_PYTHON_LINK_TARGET Python::Module)
else()
set(_PYTHON_LINK_TARGET Python::Python)
endif()

if (APPLE)
# Specifically allow dynamic lookup, here we are really targeting Python symbols.
set_target_properties(${MODULE_TARGET} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
Expand Down
48 changes: 48 additions & 0 deletions src/bindings/python/cibuildwheel.setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
""" libCellML Library: A library for the parsing, printing, and manipulation
of CellML 2.0 compliant models.

"""

classifiers = """\
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
Intended Audience :: Education
Intended Audience :: Science/Research
Programming Language :: Python
Operating System :: Microsoft :: Windows
Operating System :: Unix
Operating System :: MacOS :: MacOS X
Topic :: Software Development :: Libraries :: Python Modules
"""

import os
import platform

from skbuild import setup

cmake_args = ["-DUNIT_TESTS=OFF", "-DCOVERAGE=OFF", "-DMEMCHECK=OFF", "-DLLVM_COVERAGE=OFF", "-DCLANG_TIDY=OFF"]

if platform.system() == "Windows":
cmake_args.append("-DLibXml2_DIR=C:/Program Files (x86)/libxml2/libxml2-2.9.10/CMake/")

doclines = __doc__.split("\n")

tag = os.environ.get("LIBCELLML_VERSION_TAG", "v0.0.0")

setup(
name="libcellml",
version=tag[1:],
description=doclines[0],
author="libCellML contributors",
url="https://libcellml.org",
license="Apache 2.0",
packages=["libcellml"],
classifiers=[cl for cl in classifiers.split("\n") if cl],
long_description=open('README.rst').read(),
long_description_content_type='text/x-rst',
include_package_data=True,
cmake_source_dir="../../../",
cmake_install_target="install-wheel",
cmake_args=cmake_args,
exclude_package_data={"": ["bin/*", "cmake/*", "include/*", "lib/*"]},
)
1 change: 1 addition & 0 deletions src/bindings/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ cmake.source-dir = "../../.."
cmake.version = ">=3.26.1"
install.targets = ["install-wheel"]
ninja.version = ">=1.11"
wheel.py-api = "cp310"

[[tool.scikit-build.overrides]]
if.platform-system = "^win32"
Expand Down
Loading