Skip to content

Conversation

@JDevlieghere
Copy link
Member

@JDevlieghere JDevlieghere commented Nov 4, 2025

When building against the Python Stable API, we should use the abi3 ABI tag. Otherwise, Python will refuse to import the native shared object. This PR adds support for generating a stable ABI compatible suffix when LLDB_ENABLE_PYTHON_LIMITED_API is set.

Previously, on Darwin when building against Python 3.14, you would end up with _lldb.cpython-314-darwin.so. Now, when using the stable ABI, you get _lldb.abi3.so instead. A different version of the Python interpreter will not consider loading the former, but will load the latter.

When building against the Python Stable API, we should use the `abi3`
ABI tag. Otherwise, Python will refuse to import the native shared
object. This PR adds support for generating a stable ABI compatible
suffix when LLDB_ENABLE_PYTHON_LIMITED_API is set.
@llvmbot
Copy link
Member

llvmbot commented Nov 4, 2025

@llvm/pr-subscribers-lldb

Author: Jonas Devlieghere (JDevlieghere)

Changes

When building against the Python Stable API, we should use the abi3 ABI tag. Otherwise, Python will refuse to import the native shared object. This PR adds support for generating a stable ABI compatible suffix when LLDB_ENABLE_PYTHON_LIMITED_API is set.


Full diff: https://github.com/llvm/llvm-project/pull/166269.diff

2 Files Affected:

  • (modified) lldb/CMakeLists.txt (+5)
  • (modified) lldb/bindings/python/get-python-config.py (+7-1)
diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt
index 01b5546fee00d..0736e6ba132c8 100644
--- a/lldb/CMakeLists.txt
+++ b/lldb/CMakeLists.txt
@@ -62,11 +62,16 @@ if (LLDB_ENABLE_PYTHON)
   set(cachestring_LLDB_PYTHON_EXT_SUFFIX
     "Filename extension for native code python modules")
 
+  if (LLDB_ENABLE_PYTHON_LIMITED_API)
+    set(stable_abi "--stable-abi")
+  endif()
+
   foreach(var LLDB_PYTHON_RELATIVE_PATH LLDB_PYTHON_EXE_RELATIVE_PATH LLDB_PYTHON_EXT_SUFFIX)
     if(NOT DEFINED ${var} AND NOT CMAKE_CROSSCOMPILING)
       execute_process(
         COMMAND ${Python3_EXECUTABLE}
           ${CMAKE_CURRENT_SOURCE_DIR}/bindings/python/get-python-config.py
+          ${stable_abi}
           ${var}
         OUTPUT_VARIABLE value
         OUTPUT_STRIP_TRAILING_WHITESPACE)
diff --git a/lldb/bindings/python/get-python-config.py b/lldb/bindings/python/get-python-config.py
index ae84cbb1215a9..bf8cc48b013e1 100755
--- a/lldb/bindings/python/get-python-config.py
+++ b/lldb/bindings/python/get-python-config.py
@@ -18,6 +18,9 @@ def relpath_nodots(path, base):
 def main():
     parser = argparse.ArgumentParser(description="extract cmake variables from python")
     parser.add_argument("variable_name")
+    parser.add_argument(
+        "--stable-abi", action="store_true", help="Target the Stable C ABI"
+    )
     args = parser.parse_args()
     if args.variable_name == "LLDB_PYTHON_RELATIVE_PATH":
         # LLDB_PYTHON_RELATIVE_PATH is the relative path from lldb's prefix
@@ -68,7 +71,10 @@ def main():
                     print("sys.prefix:", sys.prefix, file=sys.stderr)
                     sys.exit(1)
     elif args.variable_name == "LLDB_PYTHON_EXT_SUFFIX":
-        print(sysconfig.get_config_var("EXT_SUFFIX"))
+        if args.stable_abi:
+            print(".abi3%s" % sysconfig.get_config_var("SHLIB_SUFFIX"))
+        else:
+            print(sysconfig.get_config_var("EXT_SUFFIX"))
     else:
         parser.error(f"unknown variable {args.variable_name}")
 

elif args.variable_name == "LLDB_PYTHON_EXT_SUFFIX":
print(sysconfig.get_config_var("EXT_SUFFIX"))
if args.stable_abi:
print(".abi3%s" % sysconfig.get_config_var("SHLIB_SUFFIX"))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find a way to get this programmatically, though it's mentioned for example in https://peps.python.org/pep-0720/.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do see code using EXTENSION_SUFFIXES and checking for the entry that contains .abi3. It doesn't say it has a set order and in theory I could make my strange platform's shared object suffix start with .abi3 and end up with .cpython-311-x86_64-linux-letsbreakassumptions.abi3askingfortrouble as one of the entries.

So yes, what you've done is fine.

Copy link
Member

@medismailben medismailben left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link
Collaborator

@DavidSpickett DavidSpickett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I tried to find a citation for the . being included and the best I could find was this bug report comment - https://bugs.python.org/msg185870.

Clearly it works for you though so it must include the ..

@JDevlieghere JDevlieghere merged commit 9564b26 into llvm:main Nov 5, 2025
12 checks passed
@JDevlieghere JDevlieghere deleted the use-abi3-suffix branch November 5, 2025 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants