From f841cf96009b972209b0dea411dc049ae4bba997 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 27 Jul 2026 14:24:41 +0300 Subject: [PATCH 1/2] [3.15] gh-154070: Build the curses module wide by capability, not by name (GH-154071) configure built the module wide (HAVE_NCURSESW) only for a library found under the name ncursesw. Probe for the wide API too, so a widec-built ncurses keeping the plain name (pkgsrc, macOS) is built wide. 3.15 has no --with-curses, so the probe is guarded on curses being found rather than on the selected backend. (cherry picked from commit 2db8ca79e0d10f134768250ac530bad45ce2758b) Co-Authored-By: Claude Opus 5 (1M context) --- ...-07-19-12-16-31.gh-issue-154070.f5da07.rst | 4 + configure | 77 +++++++++++++++++++ configure.ac | 25 ++++++ 3 files changed, 106 insertions(+) create mode 100644 Misc/NEWS.d/next/Build/2026-07-19-12-16-31.gh-issue-154070.f5da07.rst diff --git a/Misc/NEWS.d/next/Build/2026-07-19-12-16-31.gh-issue-154070.f5da07.rst b/Misc/NEWS.d/next/Build/2026-07-19-12-16-31.gh-issue-154070.f5da07.rst new file mode 100644 index 000000000000000..31c6fd3ece35322 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-07-19-12-16-31.gh-issue-154070.f5da07.rst @@ -0,0 +1,4 @@ +Build the :mod:`curses` module against a wide-character capable ncurses +even when it is not named ``ncursesw`` -- for example the pkgsrc ncurses on +NetBSD and illumos, or the system ncurses on macOS. Such a library +previously produced a narrow build. diff --git a/configure b/configure index dd506e6899515b2..df714e3eeb8e409 100755 --- a/configure +++ b/configure @@ -29578,6 +29578,83 @@ fi PANEL_CFLAGS=$(echo $PANEL_CFLAGS | sed 's/-D_XOPEN_SOURCE=600//g') +if test "x$have_curses" = xno +then : + +else case e in #( + e) + save_CFLAGS=$CFLAGS +save_CPPFLAGS=$CPPFLAGS +save_LDFLAGS=$LDFLAGS +save_LIBS=$LIBS + + + as_fn_append CPPFLAGS " $CURSES_CFLAGS" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether curses supports wide characters" >&5 +printf %s "checking whether curses supports wide characters... " >&6; } +if test ${ac_cv_curses_wide+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define NCURSES_OPAQUE 0 +#if defined(HAVE_NCURSESW_NCURSES_H) +# include +#elif defined(HAVE_NCURSESW_CURSES_H) +# include +#elif defined(HAVE_NCURSES_NCURSES_H) +# include +#elif defined(HAVE_NCURSES_CURSES_H) +# include +#elif defined(HAVE_NCURSES_H) +# include +#elif defined(HAVE_CURSES_H) +# include +#endif + +int +main (void) +{ + + cchar_t wcval; + setcchar(&wcval, L"x", A_NORMAL, 0, NULL); + add_wch(&wcval); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_curses_wide=yes +else case e in #( + e) ac_cv_curses_wide=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_curses_wide" >&5 +printf "%s\n" "$ac_cv_curses_wide" >&6; } + +CFLAGS=$save_CFLAGS +CPPFLAGS=$save_CPPFLAGS +LDFLAGS=$save_LDFLAGS +LIBS=$save_LIBS + + + if test "x$ac_cv_curses_wide" = xyes +then : + printf "%s\n" "#define HAVE_NCURSESW 1" >>confdefs.h + +fi + ;; +esac +fi + # On Solaris, term.h requires curses.h ac_fn_c_check_header_compile "$LINENO" "term.h" "ac_cv_header_term_h" " #define NCURSES_OPAQUE 0 diff --git a/configure.ac b/configure.ac index 73d0bb48ea8f4f8..8a1541e2db62ce0 100644 --- a/configure.ac +++ b/configure.ac @@ -7194,6 +7194,31 @@ AS_VAR_IF([ac_sys_system], [Darwin], [ dnl pyconfig.h defines _XOPEN_SOURCE=700 PANEL_CFLAGS=$(echo $PANEL_CFLAGS | sed 's/-D_XOPEN_SOURCE=600//g') +dnl A curses that is not named "ncursesw" can still be wide-character capable: +dnl the system curses of NetBSD, or an ncurses built with --enable-widec that +dnl keeps the plain name (pkgsrc, macOS). Probe for the wide API and, if +dnl present, build the module wide by defining HAVE_NCURSESW. +AS_VAR_IF([have_curses], [no], [], [ + WITH_SAVE_ENV([ + dnl Use the adjusted CURSES_CFLAGS (e.g. macOS's -D_XOPEN_SOURCE_EXTENDED) + dnl so the wide-character declarations are visible to the probe. + AS_VAR_APPEND([CPPFLAGS], [" $CURSES_CFLAGS"]) + AC_CACHE_CHECK([whether curses supports wide characters], + [ac_cv_curses_wide], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM([_CURSES_INCLUDES], [[ + cchar_t wcval; + setcchar(&wcval, L"x", A_NORMAL, 0, NULL); + add_wch(&wcval); + ]])], + [ac_cv_curses_wide=yes], + [ac_cv_curses_wide=no])]) + ]) + dnl HAVE_NCURSESW marks the wide (cchar_t) curses API; its template comes + dnl from the ncursesw pkg-config check above, so no description here. + AS_VAR_IF([ac_cv_curses_wide], [yes], [AC_DEFINE([HAVE_NCURSESW], [1])]) +]) + # On Solaris, term.h requires curses.h AC_CHECK_HEADERS([term.h], [], [], _CURSES_INCLUDES) From 603c80f9d2a8ec8bd21a11665a346fcc7a96a7e7 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 27 Jul 2026 15:17:55 +0300 Subject: [PATCH 2/2] Don't leak curses CPPFLAGS into the whole-interpreter build The wide-character probe ran inside a nested WITH_SAVE_ENV, whose single CPPFLAGS save slot is not reentrant, so the outer restore leaked $CURSES_CFLAGS and $PANEL_CFLAGS (-D_XOPEN_SOURCE=600) into CONFIGURE_CPPFLAGS and thus into every translation unit, producing a '_XOPEN_SOURCE' redefined warning against pyconfig.h on every file. Save and restore CPPFLAGS with a dedicated variable around the probe, as on the main branch. --- configure | 25 +++++++------------------ configure.ac | 32 +++++++++++++++++--------------- 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/configure b/configure index df714e3eeb8e409..51259e192b482cf 100755 --- a/configure +++ b/configure @@ -29583,14 +29583,9 @@ then : else case e in #( e) - save_CFLAGS=$CFLAGS -save_CPPFLAGS=$CPPFLAGS -save_LDFLAGS=$LDFLAGS -save_LIBS=$LIBS - - - as_fn_append CPPFLAGS " $CURSES_CFLAGS" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether curses supports wide characters" >&5 + save_curses_cppflags=$CPPFLAGS + as_fn_append CPPFLAGS " $CURSES_CFLAGS" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether curses supports wide characters" >&5 printf %s "checking whether curses supports wide characters... " >&6; } if test ${ac_cv_curses_wide+y} then : @@ -29618,9 +29613,9 @@ int main (void) { - cchar_t wcval; - setcchar(&wcval, L"x", A_NORMAL, 0, NULL); - add_wch(&wcval); + cchar_t wcval; + setcchar(&wcval, L"x", A_NORMAL, 0, NULL); + add_wch(&wcval); ; return 0; @@ -29639,13 +29634,7 @@ esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_curses_wide" >&5 printf "%s\n" "$ac_cv_curses_wide" >&6; } - -CFLAGS=$save_CFLAGS -CPPFLAGS=$save_CPPFLAGS -LDFLAGS=$save_LDFLAGS -LIBS=$save_LIBS - - + CPPFLAGS=$save_curses_cppflags if test "x$ac_cv_curses_wide" = xyes then : printf "%s\n" "#define HAVE_NCURSESW 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index 8a1541e2db62ce0..367234b6e9bf477 100644 --- a/configure.ac +++ b/configure.ac @@ -7199,21 +7199,23 @@ dnl the system curses of NetBSD, or an ncurses built with --enable-widec that dnl keeps the plain name (pkgsrc, macOS). Probe for the wide API and, if dnl present, build the module wide by defining HAVE_NCURSESW. AS_VAR_IF([have_curses], [no], [], [ - WITH_SAVE_ENV([ - dnl Use the adjusted CURSES_CFLAGS (e.g. macOS's -D_XOPEN_SOURCE_EXTENDED) - dnl so the wide-character declarations are visible to the probe. - AS_VAR_APPEND([CPPFLAGS], [" $CURSES_CFLAGS"]) - AC_CACHE_CHECK([whether curses supports wide characters], - [ac_cv_curses_wide], - [AC_LINK_IFELSE( - [AC_LANG_PROGRAM([_CURSES_INCLUDES], [[ - cchar_t wcval; - setcchar(&wcval, L"x", A_NORMAL, 0, NULL); - add_wch(&wcval); - ]])], - [ac_cv_curses_wide=yes], - [ac_cv_curses_wide=no])]) - ]) + dnl Use the adjusted CURSES_CFLAGS (e.g. macOS's -D_XOPEN_SOURCE_EXTENDED) + dnl so the wide-character declarations are visible to the probe. This runs + dnl inside an outer WITH_SAVE_ENV, whose single CPPFLAGS save slot is not + dnl reentrant, so save and restore CPPFLAGS with a dedicated variable here. + save_curses_cppflags=$CPPFLAGS + AS_VAR_APPEND([CPPFLAGS], [" $CURSES_CFLAGS"]) + AC_CACHE_CHECK([whether curses supports wide characters], + [ac_cv_curses_wide], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM([_CURSES_INCLUDES], [[ + cchar_t wcval; + setcchar(&wcval, L"x", A_NORMAL, 0, NULL); + add_wch(&wcval); + ]])], + [ac_cv_curses_wide=yes], + [ac_cv_curses_wide=no])]) + CPPFLAGS=$save_curses_cppflags dnl HAVE_NCURSESW marks the wide (cchar_t) curses API; its template comes dnl from the ncursesw pkg-config check above, so no description here. AS_VAR_IF([ac_cv_curses_wide], [yes], [AC_DEFINE([HAVE_NCURSESW], [1])])