Skip to content

Commit 430846c

Browse files
authored
Merge pull request #459 from isuruf/stable
Support python stable ABI
2 parents 0b5d49e + b6894c9 commit 430846c

File tree

8 files changed

+91
-15
lines changed

8 files changed

+91
-15
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ jobs:
88
fail-fast: false
99
matrix:
1010
include:
11+
- BUILD_TYPE: Release
12+
PYTHON_VERSION: '3.13'
13+
BUILD_SHARED_LIBS: yes
14+
SYMENGINE_PY_LIMITED_API: '3.11'
15+
OS: ubuntu-22.04
16+
CC: gcc
17+
1118
- BUILD_TYPE: Debug
1219
WITH_BFD: yes
1320
PYTHON_VERSION: '3.12'
@@ -197,6 +204,7 @@ jobs:
197204
MAKEFLAGS: ${{ matrix.MAKEFLAGS }}
198205
BUILD_SHARED_LIBS: ${{ matrix.BUILD_SHARED_LIBS }}
199206
PYTHON_VERSION: ${{ matrix.PYTHON_VERSION }}
207+
SYMENGINE_PY_LIMITED_API: ${{ matrix.SYMENGINE_PY_LIMITED_API }}
200208

201209
- name: Deploy Documentation
202210
if: ${{ (github.ref == 'refs/heads/main' && github.repository == 'Symengine/symengine.py') || (github.ref == 'refs/heads/master' && github.repository == 'Symengine/symengine.py')}}

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ set(CMAKE_CXX_FLAGS_DEBUG ${SYMENGINE_CXX_FLAGS_DEBUG})
2323
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SYMENGINE_CXX_FLAGS}")
2424
include_directories(${SYMENGINE_INCLUDE_DIRS})
2525

26+
set(WITH_PY_LIMITED_API OFF CACHE STRING "Use CPython's limited API")
2627
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
2728
find_package(Python REQUIRED)
2829
find_package(Cython REQUIRED)

appveyor.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ image: "Visual Studio 2019"
44

55
environment:
66
global:
7-
PLATFORMTOOLSET: "v140"
7+
PLATFORMTOOLSET: "v142"
88

99
matrix:
1010
- BUILD_TYPE: "Release"
@@ -107,8 +107,8 @@ install:
107107
- mkdir build
108108
- cd build
109109

110-
- if [%COMPILER%]==[MSVC15] if [%PLATFORM%]==[Win32] set "CMAKE_GENERATOR=Visual Studio 14 2015"
111-
- if [%COMPILER%]==[MSVC15] if [%PLATFORM%]==[x64] set "CMAKE_GENERATOR=Visual Studio 14 2015 Win64"
110+
- if [%COMPILER%]==[MSVC15] set "CMAKE_GENERATOR=Visual Studio 16 2019"
111+
- if [%COMPILER%]==[MSVC15] set "CMAKE_GENERATOR_PLATFORM=%PLATFORM%"
112112
- if [%COMPILER%]==[MinGW] set "CMAKE_GENERATOR=MinGW Makefiles"
113113
- if [%COMPILER%]==[MinGW-w64] set "CMAKE_GENERATOR=MinGW Makefiles"
114114

bin/install_travis.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ if [[ "${WITH_FLINT_PY}" == "yes" ]]; then
2020
export conda_pkgs="${conda_pkgs} python-flint"; # python-flint affects sympy, see e.g. sympy/sympy#26645
2121
fi
2222

23+
if [[ "${SYMENGINE_PY_LIMITED_API}" != "" ]]; then
24+
export conda_pkgs="${conda_pkgs} abi3audit"
25+
fi
26+
2327
if [[ "${WITH_SAGE}" == "yes" ]]; then
2428
# This is split to avoid the 10 minute limit
2529
conda install -q sagelib=8.1
@@ -33,4 +37,4 @@ if [[ "${WITH_SYMPY}" != "no" ]]; then
3337
pip install sympy;
3438
fi
3539

36-
conda clean --all
40+
conda clean --all

bin/test_travis.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ cd symengine-*
1414
# Build inplace so that nosetests can be run inside source directory
1515
python3 setup.py install build_ext --inplace --symengine-dir=$our_install_dir
1616

17+
if [[ "${SYMENGINE_PY_LIMITED_API:-}" != "" ]]; then
18+
python3 -m abi3audit --assume-minimum-abi3 ${SYMENGINE_PY_LIMITED_API} symengine/lib/symengine_wrapper.abi3.so -v
19+
fi
20+
1721
# Test python wrappers
1822
python3 -m pip install pytest
1923
python3 -m pytest -s -v $PWD/symengine/tests/test_*.py

cmake/FindCython.cmake

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,31 @@ IF (CYTHON_BIN)
2424
else (CYTHON_RESULT EQUAL 0)
2525
SET(Cython_Compilation_Failed TRUE)
2626
endif (CYTHON_RESULT EQUAL 0)
27+
execute_process(
28+
COMMAND ${CYTHON_BIN} --version
29+
RESULT_VARIABLE CYTHON_VERSION_RESULT
30+
OUTPUT_VARIABLE CYTHON_VERSION_OUTPUT
31+
ERROR_VARIABLE CYTHON_VERSION_ERROR
32+
)
33+
if (CYTHON_VERSION_RESULT EQUAL 0)
34+
string(STRIP ${CYTHON_VERSION_OUTPUT} CYTHON_VERSION_OUTPUT)
35+
if ("${CYTHON_VERSION_OUTPUT}" MATCHES "Cython version")
36+
string(SUBSTRING "${CYTHON_VERSION_OUTPUT}" 15 -1 CYTHON_VERSION)
37+
endif ()
38+
endif ()
39+
message(STATUS "Cython version: ${CYTHON_VERSION}")
2740
ENDIF (CYTHON_BIN)
2841

2942

3043
IF (Cython_FOUND)
3144
IF (NOT Cython_FIND_QUIETLY)
3245
MESSAGE(STATUS "Found CYTHON: ${CYTHON_BIN}")
3346
ENDIF (NOT Cython_FIND_QUIETLY)
47+
IF (WITH_PY_LIMITED_API AND "${CYTHON_VERSION}" VERSION_LESS "3.1")
48+
MESSAGE(FATAL_ERROR
49+
"Your Cython version (${CYTHON_VERSION}) is too old. Please upgrade Cython to 3.1 or newer."
50+
)
51+
ENDIF ()
3452
ELSE (Cython_FOUND)
3553
IF (Cython_FIND_REQUIRED)
3654
if(Cython_Compilation_Failed)

cmake/FindPython.cmake

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,17 @@ if ("${PY_GIL_DISABLED}" STREQUAL "True")
4848
endif()
4949

5050
if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
51-
FIND_LIBRARY(PYTHON_LIBRARY NAMES
52-
python${PYTHON_VERSION}${PY_THREAD}
53-
python${PYTHON_VERSION}m
54-
python${PYTHON_VERSION_WITHOUT_DOTS}${PY_THREAD}
55-
PATHS ${PYTHON_LIB_PATH} ${PYTHON_PREFIX_PATH}/lib ${PYTHON_PREFIX_PATH}/libs
56-
PATH_SUFFIXES ${CMAKE_LIBRARY_ARCHITECTURE}
57-
NO_DEFAULT_PATH
58-
NO_SYSTEM_ENVIRONMENT_PATH
59-
)
51+
if (WITH_PY_LIMITED_API)
52+
set(PYTHON_LIBRARY_NAMES python3)
53+
else()
54+
set(PYTHON_LIBRARY_NAMES python${PYTHON_VERSION}${PY_THREAD} python${PYTHON_VERSION}m python${PYTHON_VERSION_WITHOUT_DOTS}${PY_THREAD})
55+
endif()
56+
FIND_LIBRARY(PYTHON_LIBRARY NAMES ${PYTHON_LIBRARY_NAMES}
57+
PATHS ${PYTHON_LIB_PATH} ${PYTHON_PREFIX_PATH}/lib ${PYTHON_PREFIX_PATH}/libs
58+
PATH_SUFFIXES ${CMAKE_LIBRARY_ARCHITECTURE}
59+
NO_DEFAULT_PATH
60+
NO_SYSTEM_ENVIRONMENT_PATH
61+
)
6062
endif()
6163

6264
execute_process(
@@ -74,6 +76,14 @@ execute_process(
7476
)
7577
string(STRIP ${PYTHON_EXTENSION_SOABI_tmp} PYTHON_EXTENSION_SOABI_tmp)
7678

79+
if (WITH_PY_LIMITED_API)
80+
if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
81+
set(PYTHON_EXTENSION_SOABI_tmp "")
82+
else()
83+
set(PYTHON_EXTENSION_SOABI_tmp ".abi3")
84+
endif()
85+
endif()
86+
7787
set(PYTHON_EXTENSION_SOABI ${PYTHON_EXTENSION_SOABI_tmp}
7888
CACHE STRING "Suffix for python extensions")
7989

@@ -143,5 +153,12 @@ macro(ADD_PYTHON_LIBRARY name)
143153
target_compile_definitions(${name} PRIVATE Py_GIL_DISABLED=1)
144154
ENDIF()
145155
ENDIF()
146-
156+
IF(WITH_PY_LIMITED_API)
157+
target_compile_definitions(
158+
${name}
159+
PRIVATE
160+
Py_LIMITED_API=${WITH_PY_LIMITED_API}
161+
CYTHON_LIMITED_API=1
162+
)
163+
ENDIF()
147164
endmacro(ADD_PYTHON_LIBRARY)

setup.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@
1010
"Python %d.%d detected" % sys.version_info[:2])
1111
sys.exit(-1)
1212

13+
def _get_limited_api():
14+
value = os.environ.get("SYMENGINE_PY_LIMITED_API")
15+
if not value:
16+
return None
17+
else:
18+
version = tuple(map(int, value.split(".")))
19+
if version < (3, 11):
20+
raise ValueError(f"symengine needs at least python 3.11 limited API support. Got {value}")
21+
return version
22+
23+
limited_api = _get_limited_api()
24+
1325
# use setuptools by default as per the official advice at:
1426
# packaging.python.org/en/latest/current.html#packaging-tool-recommendations
1527
use_setuptools = True
@@ -65,6 +77,7 @@ def get_build_dir(dist):
6577
('build-type=', None, 'build type: Release or Debug'),
6678
('define=', 'D',
6779
'options to cmake <var>:<type>=<value>'),
80+
('py-limited-api=', None, 'Use Py_LIMITED_API with given version.'),
6881
]
6982

7083
def _process_define(arg):
@@ -122,6 +135,11 @@ def cmake_build(self):
122135
cmake_cmd.extend(process_opts(cmake_opts))
123136
if not path.exists(path.join(build_dir, "CMakeCache.txt")):
124137
cmake_cmd.extend(self.get_generator())
138+
139+
if limited_api:
140+
h = limited_api[0] * 16**6 + limited_api[1] * 16**4
141+
cmake_cmd.append(f"-DWITH_PY_LIMITED_API={h}")
142+
125143
if subprocess.call(cmake_cmd, cwd=build_dir) != 0:
126144
raise OSError("error calling cmake")
127145

@@ -202,11 +220,17 @@ def run(self):
202220
}
203221

204222
try:
205-
from wheel.bdist_wheel import bdist_wheel
223+
try:
224+
from setuptools.command.bdist_wheel import bdist_wheel
225+
except ImportError:
226+
from wheel.bdist_wheel import bdist_wheel
227+
206228
class BdistWheelWithCmake(bdist_wheel):
207229
def finalize_options(self):
208230
bdist_wheel.finalize_options(self)
209231
self.root_is_pure = False
232+
if limited_api:
233+
self.py_limited_api = "cp" + "".join(str(c) for c in limited_api)
210234
cmdclass["bdist_wheel"] = BdistWheelWithCmake
211235
except ImportError:
212236
pass

0 commit comments

Comments
 (0)