diff --git a/.github/workflows/wheel.yaml b/.github/workflows/wheel.yaml index abf00595..0d4351f9 100644 --- a/.github/workflows/wheel.yaml +++ b/.github/workflows/wheel.yaml @@ -47,11 +47,12 @@ jobs: - name: Build wheels uses: pypa/cibuildwheel@v3.4.1 env: + CIBW_BUILD: "cp310-*" CIBW_BUILD_FRONTEND: "build[uv]" CIBW_ARCHS_LINUX: auto64 CIBW_ARCHS_WINDOWS: auto64 CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 - CIBW_SKIP: "*-musllinux* pp*" + CIBW_SKIP: "*-musllinux*" CIBW_TEST_COMMAND: "pytest -s --pdb {project}/modules" CIBW_TEST_REQUIRES: pytest MACOSX_DEPLOYMENT_TARGET: 13.00 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a1faa68..56321d21 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ else() endif() # Check required CMake version -cmake_minimum_required(VERSION 3.25.0) +cmake_minimum_required(VERSION 3.26.0) cmake_policy(SET CMP0054 NEW) # Only interpret if() arguments as variables or keywords when unquoted. cmake_policy(SET CMP0076 NEW) # target_sources() command converts relative paths to absolute. diff --git a/cmake/recipes/external/nanobind.cmake b/cmake/recipes/external/nanobind.cmake index fbb2207e..67d50c3b 100644 --- a/cmake/recipes/external/nanobind.cmake +++ b/cmake/recipes/external/nanobind.cmake @@ -19,7 +19,7 @@ include(CPM) CPMAddPackage( NAME nanobind GITHUB_REPOSITORY wjakob/nanobind - GIT_TAG v2.13.0 + GIT_TAG v3.0.0-dev5 DOWNLOAD_ONLY ON ) diff --git a/cmake/recipes/external/python.cmake b/cmake/recipes/external/python.cmake index 919c4bc6..cd8b7b99 100644 --- a/cmake/recipes/external/python.cmake +++ b/cmake/recipes/external/python.cmake @@ -9,9 +9,13 @@ # OF ANY KIND, either express or implied. See the License for the specific language # governing permissions and limitations under the License. # -if(TARGET Python::Module) +if(TARGET Python::Module AND TARGET Python::SABIModule) return() endif() set(Python_FIND_VIRTUALENV FIRST) -find_package(Python 3.9 COMPONENTS Interpreter Development.Module REQUIRED) +find_package( + Python 3.10 + COMPONENTS Interpreter Development.Module Development.SABIModule + REQUIRED +) diff --git a/modules/core/python/include/lagrange/python/utils/StubType.h b/modules/core/python/include/lagrange/python/utils/StubType.h index a1a210e5..c9f70393 100644 --- a/modules/core/python/include/lagrange/python/utils/StubType.h +++ b/modules/core/python/include/lagrange/python/utils/StubType.h @@ -55,7 +55,7 @@ struct type_caster> NB_TYPE_CASTER(Wrapper, const_name(Hint::value)) - bool from_python(handle src, uint8_t flags, cleanup_list* cleanup) noexcept + bool from_python(handle src, uint32_t flags, cleanup_list* cleanup) noexcept { TCaster caster; if (!caster.from_python(src, flags, cleanup)) return false; diff --git a/modules/core/python/include/lagrange/python/utils/bind_safe_vector.h b/modules/core/python/include/lagrange/python/utils/bind_safe_vector.h index bd3ba5b7..6268ada3 100644 --- a/modules/core/python/include/lagrange/python/utils/bind_safe_vector.h +++ b/modules/core/python/include/lagrange/python/utils/bind_safe_vector.h @@ -29,7 +29,10 @@ NAMESPACE_BEGIN(NB_NAMESPACE) -template +template < + typename Vector, + rv_policy::value Policy = rv_policy::automatic_reference_v, + typename... Args> class_ bind_safe_vector(handle scope, const char* name, Args&&... args) { using ValueRef = typename detail::iterator_access::result_type; @@ -43,7 +46,7 @@ class_ bind_safe_vector(handle scope, const char* name, Args&&... args) static_assert( !detail::is_base_caster_v> || detail::is_copy_constructible_v || - (Policy != rv_policy::automatic_reference && Policy != rv_policy::copy), + (Policy != rv_policy::automatic_reference_v && Policy != rv_policy::copy_v), "bind_safe_vector(): the generated __getitem__ would copy elements, so the " "element type must be copy-constructible"); @@ -83,7 +86,7 @@ class_ bind_safe_vector(handle scope, const char* name, Args&&... args) [](Vector& v, Py_ssize_t i) -> ValueRef { return v.Vector::Super::operator[](detail::wrap(i, v.size())); }, - Policy) + rv_policy::policy_tag{}) .def("clear", [](Vector& v) { v.clear(); }, "Remove all items from list."); diff --git a/modules/core/python/src/logging.cpp b/modules/core/python/src/logging.cpp index 4de5cb50..5e3ee5fc 100644 --- a/modules/core/python/src/logging.cpp +++ b/modules/core/python/src/logging.cpp @@ -42,7 +42,7 @@ class PythonLoggingSink : public spdlog::sinks::base_sink void sink_it_(const spdlog::details::log_msg& msg) override { // Logging in python requires the current thread to hold the GIL. - if (!PyGILState_Check()) return; + if (!NB_CALL(gil_check)()) return; auto payload = msg.payload; auto res = nb::str(payload.data(), payload.size()); @@ -62,7 +62,7 @@ class PythonLoggingSink : public spdlog::sinks::base_sink void flush_() override { // Logging in python requires the current thread to hold the GIL. - if (!PyGILState_Check()) return; + if (!NB_CALL(gil_check)()) return; auto handlers = m_py_logger.attr("handlers"); for (auto handler : handlers) { diff --git a/modules/python/CMakeLists.txt b/modules/python/CMakeLists.txt index 501bb9dc..6861c4d9 100644 --- a/modules/python/CMakeLists.txt +++ b/modules/python/CMakeLists.txt @@ -22,8 +22,7 @@ endif() # 1. define module include(nanobind) lagrange_find_package(TBB CONFIG REQUIRED) -nanobind_add_module(lagrange_python NB_STATIC) -set_target_properties(nanobind-static PROPERTIES FOLDER third_party) +nanobind_add_module(lagrange_python BACKEND_MODULE nanobind_backend) add_library(lagrange::python ALIAS lagrange_python) set_target_properties(lagrange_python PROPERTIES FOLDER "${LAGRANGE_IDE_PREFIX}Lagrange/Modules" diff --git a/modules/scene/python/src/bind_value.h b/modules/scene/python/src/bind_value.h index 900d30ad..455d1364 100644 --- a/modules/scene/python/src/bind_value.h +++ b/modules/scene/python/src/bind_value.h @@ -24,7 +24,7 @@ struct type_caster NB_TYPE_CASTER(lagrange::scene::Value, const_name("int | float | str | list | dict | bool")); template - bool try_cast(const handle& src, uint8_t flags, cleanup_list* cleanup) + bool try_cast(const handle& src, uint32_t flags, cleanup_list* cleanup) { using CasterT = make_caster; @@ -34,7 +34,7 @@ struct type_caster return true; } - bool from_python(handle src, uint8_t flags, cleanup_list* cleanup) noexcept + bool from_python(handle src, uint32_t flags, cleanup_list* cleanup) noexcept { if (PyNumber_Check(src.ptr())) { lagrange::logger().debug("Number!"); @@ -48,7 +48,7 @@ struct type_caster size_t n; PyObject* temp; /* Will initialize 'temp' (NULL in the case of a failure.) */ - PyObject** o = seq_get(src.ptr(), &n, &temp); + PyObject** o = NB_CALL(seq_get)(src.ptr(), &n, &temp); bool success = o != nullptr; diff --git a/pyproject.toml b/pyproject.toml index 47e33f43..37cf8460 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,7 @@ [build-system] build-backend = "scikit_build_core.build" requires = [ + "nanobind-backend==1.0.0.dev5", # must match the nanobind development release "numpy>=1.25", # needed at build time for default dtype args "scikit-build-core==0.11.6", "typing-extensions~=4.1", @@ -30,6 +31,7 @@ dynamic = [ "version" ] dependencies = [ "colorama>=0.4.4; platform_system!='Windows'", "colorama>=0.4.6; platform_system=='Windows'", + "nanobind-backend==1.0.0.dev5", "numpy>=1.25", "scipy>=1.13.0", ] @@ -70,6 +72,7 @@ ninja.version = ">=1.11.1" ninja.make-fallback = false install.components = [ "Lagrange_Python_Runtime" ] wheel.packages = [ "modules/python/lagrange" ] +wheel.py-api = "cp310" build-dir = "build-python" editable.rebuild = false metadata.version.provider = "scikit_build_core.metadata.setuptools_scm"