diff --git a/Lib/test/test_build_details.py b/Lib/test/test_build_details.py index 30d9c213077ab75..52d66335752a558 100644 --- a/Lib/test/test_build_details.py +++ b/Lib/test/test_build_details.py @@ -2,6 +2,7 @@ import json import os import os.path +import shlex import sys import sysconfig import string @@ -173,6 +174,13 @@ def test_c_api(self): version = sysconfig.get_config_var('VERSION') self.assertTrue(os.path.exists(os.path.join(value['pkgconfig_path'], f'python-{version}.pc'))) + def test_extension_compiler_flags(self): + value = self.key('arbitrary_data.extension_compiler_flags') + expected = shlex.split( + sysconfig.get_config_var('FRAME_POINTER_CFLAGS') or '' + ) + self.assertEqual(value, expected) + @unittest.skipIf( generate_build_details is None, diff --git a/Makefile.pre.in b/Makefile.pre.in index 46fa26e01572cc2..ca6214cc7f120b6 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -83,6 +83,7 @@ MAKESETUP= $(srcdir)/Modules/makesetup # Compiler options OPT= @OPT@ BASECFLAGS= @BASECFLAGS@ +FRAME_POINTER_CFLAGS= @FRAME_POINTER_CFLAGS@ BASECPPFLAGS= @BASECPPFLAGS@ CONFIGURE_CFLAGS= @CFLAGS@ # CFLAGS_NODIST is used for building the interpreter and stdlib C extensions. diff --git a/Misc/NEWS.d/next/Build/2026-08-04-12-00-00.gh-issue-155170.abc123.rst b/Misc/NEWS.d/next/Build/2026-08-04-12-00-00.gh-issue-155170.abc123.rst new file mode 100644 index 000000000000000..43bdf21c7245572 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-08-04-12-00-00.gh-issue-155170.abc123.rst @@ -0,0 +1,2 @@ +Expose CPython's frame-pointer flags for extension builds in +``build-details.json``. diff --git a/PC/layout/support/builddetails.py b/PC/layout/support/builddetails.py index 6ef860eeb043545..c273e42bcf0d99f 100644 --- a/PC/layout/support/builddetails.py +++ b/PC/layout/support/builddetails.py @@ -54,6 +54,9 @@ }, "c_api": { }, + "arbitrary_data": { + "extension_compiler_flags": [], + }, } diff --git a/Tools/build/generate-build-details.py b/Tools/build/generate-build-details.py index 8272635bc627d6a..bf44302e5e29a2a 100644 --- a/Tools/build/generate-build-details.py +++ b/Tools/build/generate-build-details.py @@ -10,6 +10,7 @@ import importlib.machinery import json import os +import shlex import sys import sysconfig @@ -129,6 +130,11 @@ def generate_data(schema_version: str) -> collections.defaultdict[str, Any]: if LIBPC: data['c_api']['pkgconfig_path'] = LIBPC + frame_pointer_cflags = sysconfig.get_config_var('FRAME_POINTER_CFLAGS') or '' + data['arbitrary_data']['extension_compiler_flags'] = shlex.split( + frame_pointer_cflags + ) + return data diff --git a/configure b/configure index 836eb88e4cdb6e5..338795dec14b0b1 100755 --- a/configure +++ b/configure @@ -917,6 +917,7 @@ SHLIB_SUFFIX DSYMUTIL_PATH DSYMUTIL REGEN_JIT_COMMAND +FRAME_POINTER_CFLAGS UNIVERSAL_ARCH_FLAGS WASM_STDLIB WASM_ASSETS_DIR @@ -10494,6 +10495,8 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_frame_pointers" >&5 printf "%s\n" "$with_frame_pointers" >&6; } + +FRAME_POINTER_CFLAGS= if test "x$ac_cv_gcc_compat" = xyes then : @@ -10736,7 +10739,8 @@ esac fi if test -n "$frame_pointer_cflags" && test "x$with_frame_pointers" != xno; then - BASECFLAGS="$frame_pointer_cflags $BASECFLAGS" + FRAME_POINTER_CFLAGS="$frame_pointer_cflags" + BASECFLAGS="$FRAME_POINTER_CFLAGS $BASECFLAGS" printf "%s\n" "#define _Py_WITH_FRAME_POINTERS 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index 3a9841b1e7d0747..a9e76d439129765 100644 --- a/configure.ac +++ b/configure.ac @@ -2620,6 +2620,8 @@ AC_ARG_WITH([frame-pointers], [with_frame_pointers=yes]) AC_MSG_RESULT([$with_frame_pointers]) +AC_SUBST([FRAME_POINTER_CFLAGS]) +FRAME_POINTER_CFLAGS= AS_VAR_IF([ac_cv_gcc_compat], [yes], [ dnl Keep frame pointers in CPython, stdlib objects, and third-party dnl extensions built against this Python (BASECFLAGS propagates via @@ -2651,7 +2653,8 @@ AS_VAR_IF([ac_cv_gcc_compat], [yes], [ ]) ], [], [-Werror]) if test -n "$frame_pointer_cflags" && test "x$with_frame_pointers" != xno; then - BASECFLAGS="$frame_pointer_cflags $BASECFLAGS" + FRAME_POINTER_CFLAGS="$frame_pointer_cflags" + BASECFLAGS="$FRAME_POINTER_CFLAGS $BASECFLAGS" AC_DEFINE([_Py_WITH_FRAME_POINTERS], [1], [Define to 1 if frame unwinding via pointers is expected to work, 0 if not. Leave undefined if unknown.])