From 7b9916675c4370835d73158cffaac2a8a21534f1 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Sun, 7 Dec 2025 13:57:06 +0100 Subject: [PATCH] configure.ac: detect unusable termio operations Some termio operations are not actually usable on some architectures. For example, the TCGETA, TCSETA, TCSETAF and TCSETAW are defined with a reference to "struct termio" on alpha, hppa and sparc64, but "struct termio" is no longer defined since glibc 2.42, causing a build failure. Instead of using those operations as soon as they are defined, this commit checks more carefully that they are actually usable. Such a check cannot be done with the standard AC_CHECK_DECL() m4 macro, as this macro only checks that the #define exists, not that it is actually usable (i.e builds properly). Therefore, we introduce a PY_CHECK_CONSTANT() m4 macro, that verifies that the constant is actually usable. Signed-off-by: Thomas Petazzoni --- ...-12-07-15-06-37.gh-issue-142379.7vvmGc.rst | 9 ++ Modules/termios.c | 8 +- configure | 116 ++++++++++++++++++ configure.ac | 18 +++ pyconfig.h.in | 12 ++ 5 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2025-12-07-15-06-37.gh-issue-142379.7vvmGc.rst diff --git a/Misc/NEWS.d/next/Build/2025-12-07-15-06-37.gh-issue-142379.7vvmGc.rst b/Misc/NEWS.d/next/Build/2025-12-07-15-06-37.gh-issue-142379.7vvmGc.rst new file mode 100644 index 00000000000000..1fd35731b6a8af --- /dev/null +++ b/Misc/NEWS.d/next/Build/2025-12-07-15-06-37.gh-issue-142379.7vvmGc.rst @@ -0,0 +1,9 @@ +Some termio operations are not actually usable on some +architectures. For example, the TCGETA, TCSETA, TCSETAF and TCSETAW +are defined with a reference to "struct termio" on alpha, hppa and +sparc64, but "struct termio" is no longer defined since glibc 2.42, +causing a build failure. + +Instead of using those operations as soon as they are defined, check +more carefully that they are actually usable. This is done using a new +m4 macro PY_CHECK_CONSTANT. diff --git a/Modules/termios.c b/Modules/termios.c index b4eb06cf8ae8ac..42a619ec526eae 100644 --- a/Modules/termios.c +++ b/Modules/termios.c @@ -1116,7 +1116,7 @@ static struct constant { #ifdef TCFLSH {"TCFLSH", TCFLSH}, #endif -#ifdef TCGETA +#ifdef HAVE_TCGETA {"TCGETA", TCGETA}, #endif #ifdef TCGETS @@ -1128,13 +1128,13 @@ static struct constant { #ifdef TCSBRKP {"TCSBRKP", TCSBRKP}, #endif -#ifdef TCSETA +#ifdef HAVE_TCSETA {"TCSETA", TCSETA}, #endif -#ifdef TCSETAF +#ifdef HAVE_TCSETAF {"TCSETAF", TCSETAF}, #endif -#ifdef TCSETAW +#ifdef HAVE_TCSETAW {"TCSETAW", TCSETAW}, #endif #ifdef TCSETS diff --git a/configure b/configure index 1561f7f4134ac2..dab245507e12f5 100755 --- a/configure +++ b/configure @@ -3574,6 +3574,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then # If we're building out-of-tree, we need to make sure the following # resources get picked up before their $srcdir counterparts. @@ -34369,6 +34371,120 @@ fi # substitute multiline block, must come after last PY_STDLIB_MOD() +# gh-142379: ioctls used by Modules/termios.c but not usable on all platforms + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for TCGETA" >&5 +printf %s "checking for TCGETA... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +long val = TCGETA; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +printf "%s\n" "#define HAVE_TCGETA 1" >>confdefs.h + +else case e in #( + e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for TCSETA" >&5 +printf %s "checking for TCSETA... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +long val = TCSETA; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +printf "%s\n" "#define HAVE_TCSETA 1" >>confdefs.h + +else case e in #( + e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for TCSETAF" >&5 +printf %s "checking for TCSETAF... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +long val = TCSETAF; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +printf "%s\n" "#define HAVE_TCSETAF 1" >>confdefs.h + +else case e in #( + e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for TCSETAW" >&5 +printf %s "checking for TCSETAW... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +long val = TCSETAW; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +printf "%s\n" "#define HAVE_TCSETAW 1" >>confdefs.h + +else case e in #( + e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + # generate output files ac_config_files="$ac_config_files Makefile.pre Misc/python.pc Misc/python-embed.pc Misc/python-config.sh" diff --git a/configure.ac b/configure.ac index f2a7319d22d24b..bd276b5660c407 100644 --- a/configure.ac +++ b/configure.ac @@ -95,6 +95,18 @@ AC_DEFUN([PY_CHECK_EMSCRIPTEN_PORT], [ AS_VAR_POPDEF([py_libs]) ]) +dnl PY_CHECK_CONSTANT(TYPE, CONSTANT, [INCLUDES]) +dnl Checks whether the constant exists and is actually usable (unlike +dnl AC_CHECK_DECL that only checks if the constant exists) +AC_DEFUN([PY_CHECK_CONSTANT], [ + AC_MSG_CHECKING([for $2]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$3], [[$1 val = $2;]])], + [AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_$2], [1], + [Defined if $2 is usable])], + [AC_MSG_RESULT([no])] +)]) + AC_SUBST([BASECPPFLAGS]) if test "$srcdir" != . -a "$srcdir" != "$(pwd)"; then # If we're building out-of-tree, we need to make sure the following @@ -8245,6 +8257,12 @@ AC_SUBST([JIT_STENCILS_H]) # substitute multiline block, must come after last PY_STDLIB_MOD() AC_SUBST([MODULE_BLOCK]) +# gh-142379: ioctls used by Modules/termios.c but not usable on all platforms +PY_CHECK_CONSTANT([long], [TCGETA], [#include ]) +PY_CHECK_CONSTANT([long], [TCSETA], [#include ]) +PY_CHECK_CONSTANT([long], [TCSETAF], [#include ]) +PY_CHECK_CONSTANT([long], [TCSETAW], [#include ]) + # generate output files AC_CONFIG_FILES(m4_normalize([ Makefile.pre diff --git a/pyconfig.h.in b/pyconfig.h.in index 8a9f5ca8ec826d..108895daffcddd 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1524,9 +1524,21 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_XATTR_H +/* Defined if TCGETA is usable */ +#undef HAVE_TCGETA + /* Define to 1 if you have the 'tcgetpgrp' function. */ #undef HAVE_TCGETPGRP +/* Defined if TCSETA is usable */ +#undef HAVE_TCSETA + +/* Defined if TCSETAF is usable */ +#undef HAVE_TCSETAF + +/* Defined if TCSETAW is usable */ +#undef HAVE_TCSETAW + /* Define to 1 if you have the 'tcsetpgrp' function. */ #undef HAVE_TCSETPGRP