Skip to content
Merged
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
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ jobs:
fail-fast: false
matrix:
include:
- BUILD_TYPE: Release
PYTHON_VERSION: '3.13'
BUILD_SHARED_LIBS: yes
SYMENGINE_PY_LIMITED_API: '3.11'
OS: ubuntu-22.04
CC: gcc

- BUILD_TYPE: Debug
WITH_BFD: yes
PYTHON_VERSION: '3.12'
Expand Down Expand Up @@ -197,6 +204,7 @@ jobs:
MAKEFLAGS: ${{ matrix.MAKEFLAGS }}
BUILD_SHARED_LIBS: ${{ matrix.BUILD_SHARED_LIBS }}
PYTHON_VERSION: ${{ matrix.PYTHON_VERSION }}
SYMENGINE_PY_LIMITED_API: ${{ matrix.SYMENGINE_PY_LIMITED_API }}

- name: Deploy Documentation
if: ${{ (github.ref == 'refs/heads/main' && github.repository == 'Symengine/symengine.py') || (github.ref == 'refs/heads/master' && github.repository == 'Symengine/symengine.py')}}
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ set(CMAKE_CXX_FLAGS_DEBUG ${SYMENGINE_CXX_FLAGS_DEBUG})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SYMENGINE_CXX_FLAGS}")
include_directories(${SYMENGINE_INCLUDE_DIRS})

set(WITH_PY_LIMITED_API OFF CACHE STRING "Use CPython's limited API")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
find_package(Python REQUIRED)
find_package(Cython REQUIRED)
Expand Down
6 changes: 3 additions & 3 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ image: "Visual Studio 2019"

environment:
global:
PLATFORMTOOLSET: "v140"
PLATFORMTOOLSET: "v142"

matrix:
- BUILD_TYPE: "Release"
Expand Down Expand Up @@ -107,8 +107,8 @@ install:
- mkdir build
- cd build

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

Expand Down
6 changes: 5 additions & 1 deletion bin/install_travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ if [[ "${WITH_FLINT_PY}" == "yes" ]]; then
export conda_pkgs="${conda_pkgs} python-flint"; # python-flint affects sympy, see e.g. sympy/sympy#26645
fi

if [[ "${SYMENGINE_PY_LIMITED_API}" != "" ]]; then
export conda_pkgs="${conda_pkgs} abi3audit"
fi

if [[ "${WITH_SAGE}" == "yes" ]]; then
# This is split to avoid the 10 minute limit
conda install -q sagelib=8.1
Expand All @@ -33,4 +37,4 @@ if [[ "${WITH_SYMPY}" != "no" ]]; then
pip install sympy;
fi

conda clean --all
conda clean --all
4 changes: 4 additions & 0 deletions bin/test_travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ cd symengine-*
# Build inplace so that nosetests can be run inside source directory
python3 setup.py install build_ext --inplace --symengine-dir=$our_install_dir

if [[ "${SYMENGINE_PY_LIMITED_API:-}" != "" ]]; then
python3 -m abi3audit --assume-minimum-abi3 ${SYMENGINE_PY_LIMITED_API} symengine/lib/symengine_wrapper.abi3.so -v
fi

# Test python wrappers
python3 -m pip install pytest
python3 -m pytest -s -v $PWD/symengine/tests/test_*.py
Expand Down
18 changes: 18 additions & 0 deletions cmake/FindCython.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,31 @@ IF (CYTHON_BIN)
else (CYTHON_RESULT EQUAL 0)
SET(Cython_Compilation_Failed TRUE)
endif (CYTHON_RESULT EQUAL 0)
execute_process(
COMMAND ${CYTHON_BIN} --version
RESULT_VARIABLE CYTHON_VERSION_RESULT
OUTPUT_VARIABLE CYTHON_VERSION_OUTPUT
ERROR_VARIABLE CYTHON_VERSION_ERROR
)
if (CYTHON_VERSION_RESULT EQUAL 0)
string(STRIP ${CYTHON_VERSION_OUTPUT} CYTHON_VERSION_OUTPUT)
if ("${CYTHON_VERSION_OUTPUT}" MATCHES "Cython version")
string(SUBSTRING "${CYTHON_VERSION_OUTPUT}" 15 -1 CYTHON_VERSION)
endif ()
endif ()
message(STATUS "Cython version: ${CYTHON_VERSION}")
ENDIF (CYTHON_BIN)


IF (Cython_FOUND)
IF (NOT Cython_FIND_QUIETLY)
MESSAGE(STATUS "Found CYTHON: ${CYTHON_BIN}")
ENDIF (NOT Cython_FIND_QUIETLY)
IF (WITH_PY_LIMITED_API AND "${CYTHON_VERSION}" VERSION_LESS "3.1")
MESSAGE(FATAL_ERROR
"Your Cython version (${CYTHON_VERSION}) is too old. Please upgrade Cython to 3.1 or newer."
)
ENDIF ()
ELSE (Cython_FOUND)
IF (Cython_FIND_REQUIRED)
if(Cython_Compilation_Failed)
Expand Down
37 changes: 27 additions & 10 deletions cmake/FindPython.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,17 @@ if ("${PY_GIL_DISABLED}" STREQUAL "True")
endif()

if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
FIND_LIBRARY(PYTHON_LIBRARY NAMES
python${PYTHON_VERSION}${PY_THREAD}
python${PYTHON_VERSION}m
python${PYTHON_VERSION_WITHOUT_DOTS}${PY_THREAD}
PATHS ${PYTHON_LIB_PATH} ${PYTHON_PREFIX_PATH}/lib ${PYTHON_PREFIX_PATH}/libs
PATH_SUFFIXES ${CMAKE_LIBRARY_ARCHITECTURE}
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
if (WITH_PY_LIMITED_API)
set(PYTHON_LIBRARY_NAMES python3)
else()
set(PYTHON_LIBRARY_NAMES python${PYTHON_VERSION}${PY_THREAD} python${PYTHON_VERSION}m python${PYTHON_VERSION_WITHOUT_DOTS}${PY_THREAD})
endif()
FIND_LIBRARY(PYTHON_LIBRARY NAMES ${PYTHON_LIBRARY_NAMES}
PATHS ${PYTHON_LIB_PATH} ${PYTHON_PREFIX_PATH}/lib ${PYTHON_PREFIX_PATH}/libs
PATH_SUFFIXES ${CMAKE_LIBRARY_ARCHITECTURE}
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
endif()

execute_process(
Expand All @@ -74,6 +76,14 @@ execute_process(
)
string(STRIP ${PYTHON_EXTENSION_SOABI_tmp} PYTHON_EXTENSION_SOABI_tmp)

if (WITH_PY_LIMITED_API)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(PYTHON_EXTENSION_SOABI_tmp "")
else()
set(PYTHON_EXTENSION_SOABI_tmp ".abi3")
endif()
endif()

set(PYTHON_EXTENSION_SOABI ${PYTHON_EXTENSION_SOABI_tmp}
CACHE STRING "Suffix for python extensions")

Expand Down Expand Up @@ -143,5 +153,12 @@ macro(ADD_PYTHON_LIBRARY name)
target_compile_definitions(${name} PRIVATE Py_GIL_DISABLED=1)
ENDIF()
ENDIF()

IF(WITH_PY_LIMITED_API)
target_compile_definitions(
${name}
PRIVATE
Py_LIMITED_API=${WITH_PY_LIMITED_API}
CYTHON_LIMITED_API=1
)
ENDIF()
endmacro(ADD_PYTHON_LIBRARY)
26 changes: 25 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@
"Python %d.%d detected" % sys.version_info[:2])
sys.exit(-1)

def _get_limited_api():
value = os.environ.get("SYMENGINE_PY_LIMITED_API")
if not value:
return None
else:
version = tuple(map(int, value.split(".")))
if version < (3, 11):
raise ValueError(f"symengine needs at least python 3.11 limited API support. Got {value}")
return version

limited_api = _get_limited_api()

# use setuptools by default as per the official advice at:
# packaging.python.org/en/latest/current.html#packaging-tool-recommendations
use_setuptools = True
Expand Down Expand Up @@ -65,6 +77,7 @@ def get_build_dir(dist):
('build-type=', None, 'build type: Release or Debug'),
('define=', 'D',
'options to cmake <var>:<type>=<value>'),
('py-limited-api=', None, 'Use Py_LIMITED_API with given version.'),
]

def _process_define(arg):
Expand Down Expand Up @@ -122,6 +135,11 @@ def cmake_build(self):
cmake_cmd.extend(process_opts(cmake_opts))
if not path.exists(path.join(build_dir, "CMakeCache.txt")):
cmake_cmd.extend(self.get_generator())

if limited_api:
h = limited_api[0] * 16**6 + limited_api[1] * 16**4
cmake_cmd.append(f"-DWITH_PY_LIMITED_API={h}")

if subprocess.call(cmake_cmd, cwd=build_dir) != 0:
raise OSError("error calling cmake")

Expand Down Expand Up @@ -202,11 +220,17 @@ def run(self):
}

try:
from wheel.bdist_wheel import bdist_wheel
try:
from setuptools.command.bdist_wheel import bdist_wheel
except ImportError:
from wheel.bdist_wheel import bdist_wheel

class BdistWheelWithCmake(bdist_wheel):
def finalize_options(self):
bdist_wheel.finalize_options(self)
self.root_is_pure = False
if limited_api:
self.py_limited_api = "cp" + "".join(str(c) for c in limited_api)
cmdclass["bdist_wheel"] = BdistWheelWithCmake
except ImportError:
pass
Expand Down
Loading