From 3c13818785eb42152f5c12b99ad8b8f686d7b02e Mon Sep 17 00:00:00 2001 From: Oscar Benjamin Date: Tue, 9 Sep 2025 16:02:45 +0100 Subject: [PATCH] build: enable building with the limited API Cython 3.1 makes it possible to build with the limited API. This adds the necessary build configuration so that python-flint can be built with the limited API which in principle makes it possible to have abi3 wheels that can work with a range of CPython versions. Although this builds the tests crash pretty quickly in a segfault so more work would be needed to make these builds useful. For now we just enable this as an experimental build mode. When it is working it would be worth running some timings to see if it is slower than a normal build. --- meson.build | 12 +++++++++--- meson.options | 1 + pyproject.toml | 4 ++++ src/flint/flint_base/meson.build | 1 + src/flint/functions/meson.build | 1 + src/flint/meson.build | 1 + src/flint/types/acb_poly.pyx | 2 +- src/flint/types/arb.pyx | 4 ++-- src/flint/types/arb_poly.pyx | 2 +- src/flint/types/arf.pyx | 4 ++-- src/flint/types/fmpq_poly.pyx | 2 +- src/flint/types/fmpz_mod_poly.pyx | 2 +- src/flint/types/fmpz_poly.pyx | 2 +- src/flint/types/fq_default_poly.pyx | 2 +- src/flint/types/meson.build | 1 + src/flint/types/nmod_poly.pyx | 2 +- src/flint/utils/meson.build | 1 + 17 files changed, 30 insertions(+), 14 deletions(-) diff --git a/meson.build b/meson.build index 71cbc18e..a8922502 100644 --- a/meson.build +++ b/meson.build @@ -2,7 +2,8 @@ project( 'python-flint', 'cython', 'c', - meson_version : '>=1.1', + meson_version : '>=1.3.0', + default_options: ['python.allow_limited_api=false'], ) # # The minimum versions are because we know that it will not work with earlier @@ -83,15 +84,20 @@ add_project_arguments( language : 'cython' ) +# Only used if python.allow_limited_api is true (not the default) +limited_api_version = get_option('limited_api_version') + # Enable free-threading if Cython is new enough. The check should be # >= 3.1.0a1 but meson gets confused by the a1 alpha release suffix. # so we go with >= 3.1 (which will be correct once 3.1 is released). cy = meson.get_compiler('cython') -if cy.version().version_compare('>=3.1') +if get_option('python.allow_limited_api') + message('Using Python limited API version ' + limited_api_version) +elif cy.version().version_compare('>=3.1') message('Enabling freethreading') add_project_arguments('-Xfreethreading_compatible=true', language : 'cython') else - message('Disabling freethreading') + message('Normal build (no freethreading and no limited API)') endif if get_option('coverage') diff --git a/meson.options b/meson.options index efaf420c..d1094d31 100644 --- a/meson.options +++ b/meson.options @@ -1,3 +1,4 @@ option('coverage', type : 'boolean', value : false, description : 'enable coverage build') option('add_flint_rpath', type : 'boolean', value : false) option('flint_version_check', type: 'boolean', value : true) +option('limited_api_version', type: 'string', value : '3.12') diff --git a/pyproject.toml b/pyproject.toml index 614e66b5..bf6d0557 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,10 @@ content-type = "text/markdown" requires = ["meson-python >= 0.18", "cython >=3.1,<3.2"] build-backend = "mesonpy" +[tool.meson-python] + +limited-api = true + [tool.cython-lint] # E129 visually indented line with same indent as next logical line # Reasoning: this rule is a little controversial diff --git a/src/flint/flint_base/meson.build b/src/flint/flint_base/meson.build index f69d99f2..6057efd0 100644 --- a/src/flint/flint_base/meson.build +++ b/src/flint/flint_base/meson.build @@ -23,5 +23,6 @@ foreach ext : exts dependencies: pyflint_deps, install: true, subdir: pkgdir, + limited_api: limited_api_version, ) endforeach diff --git a/src/flint/functions/meson.build b/src/flint/functions/meson.build index 80f1f869..46d1102f 100644 --- a/src/flint/functions/meson.build +++ b/src/flint/functions/meson.build @@ -19,5 +19,6 @@ foreach ext : exts dependencies: pyflint_deps, install: true, subdir: 'flint/functions', + limited_api: limited_api_version, ) endforeach diff --git a/src/flint/meson.build b/src/flint/meson.build index 061ed3c7..f76c7781 100644 --- a/src/flint/meson.build +++ b/src/flint/meson.build @@ -31,6 +31,7 @@ foreach ext : exts dependencies: pyflint_deps, install: true, subdir: thisdir, + limited_api: limited_api_version, ) endforeach diff --git a/src/flint/types/acb_poly.pyx b/src/flint/types/acb_poly.pyx index d155f795..b52de19e 100644 --- a/src/flint/types/acb_poly.pyx +++ b/src/flint/types/acb_poly.pyx @@ -1,4 +1,4 @@ -from cpython.list cimport PyList_GET_SIZE +from cpython.list cimport PyList_Size as PyList_GET_SIZE from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_context cimport getprec from flint.flint_base.flint_base cimport flint_poly diff --git a/src/flint/types/arb.pyx b/src/flint/types/arb.pyx index 74aea43a..dab29f0e 100644 --- a/src/flint/types/arb.pyx +++ b/src/flint/types/arb.pyx @@ -1,4 +1,4 @@ -from cpython.float cimport PyFloat_AS_DOUBLE +from cpython.float cimport PyFloat_AsDouble from cpython.long cimport PyLong_Check from flint.flint_base.flint_context cimport getprec @@ -101,7 +101,7 @@ cdef int arb_set_python(arb_t x, obj, bint allow_conversion) except -1: return 1 if typecheck(obj, float): - arf_set_d(arb_midref(x), PyFloat_AS_DOUBLE(obj)) + arf_set_d(arb_midref(x), PyFloat_AsDouble(obj)) mag_zero(arb_radref(x)) return 1 diff --git a/src/flint/types/arb_poly.pyx b/src/flint/types/arb_poly.pyx index 08dc54de..f00889ff 100644 --- a/src/flint/types/arb_poly.pyx +++ b/src/flint/types/arb_poly.pyx @@ -1,4 +1,4 @@ -from cpython.list cimport PyList_GET_SIZE +from cpython.list cimport PyList_Size as PyList_GET_SIZE from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_context cimport getprec from flint.flint_base.flint_base cimport flint_poly diff --git a/src/flint/types/arf.pyx b/src/flint/types/arf.pyx index 097e8d30..d4dbea42 100644 --- a/src/flint/types/arf.pyx +++ b/src/flint/types/arf.pyx @@ -1,4 +1,4 @@ -from cpython.float cimport PyFloat_AS_DOUBLE +from cpython.float cimport PyFloat_AsDouble from flint.flint_base.flint_context cimport getprec from flint.flint_base.flint_context cimport thectx from flint.utils.typecheck cimport typecheck @@ -44,7 +44,7 @@ cdef class arf: elif typecheck(val, arf): arf_set(self.val, (val).val) elif typecheck(val, float): - arf_set_d(self.val, PyFloat_AS_DOUBLE(val)) + arf_set_d(self.val, PyFloat_AsDouble(val)) elif typecheck(val, tuple): man = any_as_fmpz(val[0]) exp = any_as_fmpz(val[1]) diff --git a/src/flint/types/fmpq_poly.pyx b/src/flint/types/fmpq_poly.pyx index ee0933d8..5781d8b0 100644 --- a/src/flint/types/fmpq_poly.pyx +++ b/src/flint/types/fmpq_poly.pyx @@ -1,4 +1,4 @@ -from cpython.list cimport PyList_GET_SIZE +from cpython.list cimport PyList_Size as PyList_GET_SIZE from flint.utils.typecheck cimport typecheck from flint.flint_base.flint_base cimport flint_poly from flint.types.fmpz_poly cimport any_as_fmpz_poly diff --git a/src/flint/types/fmpz_mod_poly.pyx b/src/flint/types/fmpz_mod_poly.pyx index ce266bee..12820bbc 100644 --- a/src/flint/types/fmpz_mod_poly.pyx +++ b/src/flint/types/fmpz_mod_poly.pyx @@ -1,4 +1,4 @@ -from cpython.list cimport PyList_GET_SIZE +from cpython.list cimport PyList_Size as PyList_GET_SIZE from flint.pyflint cimport global_random_state from flint.flintlib.functions.fmpz_mod cimport fmpz_mod_neg, fmpz_mod_set_fmpz diff --git a/src/flint/types/fmpz_poly.pyx b/src/flint/types/fmpz_poly.pyx index 504c4221..19628517 100644 --- a/src/flint/types/fmpz_poly.pyx +++ b/src/flint/types/fmpz_poly.pyx @@ -1,4 +1,4 @@ -from cpython.list cimport PyList_GET_SIZE +from cpython.list cimport PyList_Size as PyList_GET_SIZE from cpython.long cimport PyLong_Check cimport libc.stdlib diff --git a/src/flint/types/fq_default_poly.pyx b/src/flint/types/fq_default_poly.pyx index 924b6884..8972a4d7 100644 --- a/src/flint/types/fq_default_poly.pyx +++ b/src/flint/types/fq_default_poly.pyx @@ -1,5 +1,5 @@ cimport cython -from cpython.list cimport PyList_GET_SIZE +from cpython.list cimport PyList_Size as PyList_GET_SIZE from flint.flint_base.flint_base cimport flint_poly from flint.types.fmpz cimport fmpz, any_as_fmpz diff --git a/src/flint/types/meson.build b/src/flint/types/meson.build index cd8cc022..ac191e49 100644 --- a/src/flint/types/meson.build +++ b/src/flint/types/meson.build @@ -111,5 +111,6 @@ foreach ext : exts dependencies: pyflint_deps, install: true, subdir: thisdir, + limited_api: limited_api_version, ) endforeach diff --git a/src/flint/types/nmod_poly.pyx b/src/flint/types/nmod_poly.pyx index 722194fc..9fc9bd1e 100644 --- a/src/flint/types/nmod_poly.pyx +++ b/src/flint/types/nmod_poly.pyx @@ -1,5 +1,5 @@ cimport cython -from cpython.list cimport PyList_GET_SIZE +from cpython.list cimport PyList_Size as PyList_GET_SIZE from flint.flint_base.flint_base cimport flint_poly from flint.utils.typecheck cimport typecheck from flint.types.fmpz cimport fmpz, any_as_fmpz diff --git a/src/flint/utils/meson.build b/src/flint/utils/meson.build index d05a2dd9..8ec2da5c 100644 --- a/src/flint/utils/meson.build +++ b/src/flint/utils/meson.build @@ -20,5 +20,6 @@ foreach ext : exts dependencies: pyflint_deps, install: true, subdir: thisdir, + limited_api: limited_api_version, ) endforeach