diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig index 3baeaa7770e6c..f73ab768b4c42 100644 --- a/lldb/bindings/python/python-typemaps.swig +++ b/lldb/bindings/python/python-typemaps.swig @@ -220,9 +220,9 @@ AND call SWIG_fail at the same time, because it will result in a double free. } // Disable default type checking for this method to avoid SWIG dispatch issues. -// +// // Problem: SBThread::GetStopDescription has two overloads: -// 1. GetStopDescription(char* dst_or_null, size_t dst_len) +// 1. GetStopDescription(char* dst_or_null, size_t dst_len) // 2. GetStopDescription(lldb::SBStream& stream) // // SWIG generates a dispatch function to select the correct overload based on argument types. @@ -230,9 +230,9 @@ AND call SWIG_fail at the same time, because it will result in a double free. // However, this dispatcher doesn't consider typemaps that transform function signatures. // // In Python, our typemap converts GetStopDescription(char*, size_t) to GetStopDescription(int). -// The dispatcher still checks against the original (char*, size_t) signature instead of +// The dispatcher still checks against the original (char*, size_t) signature instead of // the transformed (int) signature, causing type matching to fail. -// This only affects SBThread::GetStopDescription since the type check also matches +// This only affects SBThread::GetStopDescription since the type check also matches // the argument name, which is unique to this function. %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) (char *dst_or_null, size_t dst_len) "" @@ -628,12 +628,11 @@ template <> bool SetNumberFromPyObject(double &number, PyObject *obj) { } } -// These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i, -// and fixed so they will not crash if PyObject_GetBuffer fails. -// https://github.com/swig/swig/issues/1640 -// -// I've also moved the call to PyBuffer_Release to the end of the SWIG wrapper, -// doing it right away is not legal according to the python buffer protocol. +// These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i. +// - Avoids crash if PyObject_GetBuffer fails and delays calling +// PyBuffer_Release (https://github.com/swig/swig/issues/1640) +// - Avoids using deprecated "old buffer protocol" APIs when targeting the +// Stable C API. %inline %{ struct Py_buffer_RAII { Py_buffer buffer = {}; diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig index 3a0995e84f643..9b9245eac14ce 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -128,8 +128,11 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallTypeScript( PyObject *pfunc_impl = nullptr; - if (pyfunct_wrapper && *pyfunct_wrapper && - PyFunction_Check(*pyfunct_wrapper)) { + if (pyfunct_wrapper && *pyfunct_wrapper +#ifndef Py_LIMITED_API + && PyFunction_Check(*pyfunct_wrapper) +#endif + ) { pfunc_impl = (PyObject *)(*pyfunct_wrapper); if (pfunc_impl->ob_refcnt == 1) { Py_XDECREF(pfunc_impl); diff --git a/lldb/bindings/python/python.swig b/lldb/bindings/python/python.swig index 4a5a39dc4b06d..b2823f98acac8 100644 --- a/lldb/bindings/python/python.swig +++ b/lldb/bindings/python/python.swig @@ -59,6 +59,11 @@ except ImportError: // Parameter types will be used in the autodoc string. %feature("autodoc", "1"); +// Include lldb-python first as it sets Py_LIMITED_API. +%begin %{ +#include "../source/Plugins/ScriptInterpreter/Python/lldb-python.h" +%} + %pythoncode%{ import uuid import re diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake index 4b568d27c4709..4621642890066 100644 --- a/lldb/cmake/modules/LLDBConfig.cmake +++ b/lldb/cmake/modules/LLDBConfig.cmake @@ -180,13 +180,29 @@ if (LLDB_ENABLE_PYTHON) "Path to use as PYTHONHOME in lldb. If a relative path is specified, it will be resolved at runtime relative to liblldb directory.") endif() - if (SWIG_VERSION VERSION_GREATER_EQUAL "4.2" AND NOT LLDB_EMBED_PYTHON_HOME) + set(python_limited_api_swig_version "4.2") + set(python_limited_api_python_version "3.11") + + if (SWIG_VERSION VERSION_GREATER_EQUAL python_limited_api_swig_version + AND Python3_VERSION VERSION_GREATER_EQUAL python_limited_api_python_version + AND NOT LLDB_EMBED_PYTHON_HOME) set(default_enable_python_limited_api ON) else() set(default_enable_python_limited_api OFF) endif() - option(LLDB_ENABLE_PYTHON_LIMITED_API "Force LLDB to only use the Python Limited API (requires SWIG 4.2 or later)" + option(LLDB_ENABLE_PYTHON_LIMITED_API "Only use the Python Limited API (requires at least Python 3.11 and SWIG 4.2)" ${default_enable_python_limited_api}) + + # Diagnose unsupported configurations. + if (LLDB_ENABLE_PYTHON_LIMITED_API AND LLDB_EMBED_PYTHON_HOME) + message(SEND_ERROR "LLDB_ENABLE_PYTHON_LIMITED_API is not compatible with LLDB_EMBED_PYTHON_HOME") + endif() + if (LLDB_ENABLE_PYTHON_LIMITED_API AND Python3_VERSION VERSION_LESS python_limited_api_python_version) + message(SEND_ERROR "LLDB_ENABLE_PYTHON_LIMITED_API is not compatible with Python ${Python3_VERSION} (requires Python ${python_limited_api_python_version})") + endif() + if (LLDB_ENABLE_PYTHON_LIMITED_API AND SWIG_VERSION VERSION_LESS python_limited_api_swig_version) + message(SEND_ERROR "LLDB_ENABLE_PYTHON_LIMITED_API is not compatible with SWIG ${SWIG_VERSION} (requires SWIG ${python_limited_api_swig_version})") + endif() else() # Even if Python scripting is disabled, we still need a Python interpreter to # build, for example to generate SBLanguages.h. diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h index 0c281793613a5..98941f504e44c 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h @@ -45,12 +45,13 @@ static llvm::Expected *g_fcxx_modules_workaround [[maybe_unused]]; #include #endif -#define LLDB_MINIMUM_PYTHON_VERSION 0x03080000 - -#if LLDB_ENABLE_PYTHON_LIMITED_API // If defined, LLDB will be ABI-compatible with all Python 3 releases from the // specified one onward, and can use Limited API introduced up to that version. +#if LLDB_ENABLE_PYTHON_LIMITED_API +#define LLDB_MINIMUM_PYTHON_VERSION 0x030b0000 #define Py_LIMITED_API LLDB_MINIMUM_PYTHON_VERSION +#else +#define LLDB_MINIMUM_PYTHON_VERSION 0x03080000 #endif // Include python for non windows machines