From e241894aa3dbb30ef60561ca392c01d9f60c7817 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Sep 2023 18:30:18 +0200 Subject: [PATCH] gh-109054: configure checks if libatomic is needed Fix building the _testcapi extension on Linux AArch64 which requires linking to libatomic when is used: the _Py_atomic_or_uint64() function requires libatomic __atomic_fetch_or_8() on this platform. The configure script now checks if linking to libatomic is needed and generates a new LIBATOMIC variable used to build the _testcapi extension. Building the _testcapi extension now uses the LIBATOMIC variable in its LDFLAGS, since Modules/_testcapi/pyatomic.c uses . --- Makefile.pre.in | 1 + ...-09-07-19-58-05.gh-issue-109054.5r3S3l.rst | 6 ++ configure | 90 ++++++++++++++++++- configure.ac | 68 +++++++++++++- 4 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2023-09-07-19-58-05.gh-issue-109054.5r3S3l.rst diff --git a/Makefile.pre.in b/Makefile.pre.in index aa3eaabc7559f61..7c2f7dff6d8cfbf 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -267,6 +267,7 @@ STATIC_LIBPYTHON= @STATIC_LIBPYTHON@ LIBS= @LIBS@ LIBM= @LIBM@ +LIBATOMIC= @LIBATOMIC@ LIBC= @LIBC@ SYSLIBS= $(LIBM) $(LIBC) SHLIBS= @SHLIBS@ diff --git a/Misc/NEWS.d/next/Build/2023-09-07-19-58-05.gh-issue-109054.5r3S3l.rst b/Misc/NEWS.d/next/Build/2023-09-07-19-58-05.gh-issue-109054.5r3S3l.rst new file mode 100644 index 000000000000000..d86a110e0de68c4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2023-09-07-19-58-05.gh-issue-109054.5r3S3l.rst @@ -0,0 +1,6 @@ +Fix building the ``_testcapi`` extension on Linux AArch64 which requires +linking to libatomic when ```` is used: the +``_Py_atomic_or_uint64()`` function requires libatomic +``__atomic_fetch_or_8()`` on this platform. The configure script now checks +if linking to libatomic is needed and generates a new LIBATOMIC variable +used to build the _testcapi extension. Patch by Victor Stinner. diff --git a/configure b/configure index d73b4b271ac7199..ed0c905ceb34a17 100755 --- a/configure +++ b/configure @@ -810,6 +810,7 @@ MODULE_TIME_TRUE MODULE__IO_FALSE MODULE__IO_TRUE MODULE_BUILDTYPE +LIBATOMIC TEST_MODULES LIBB2_LIBS LIBB2_CFLAGS @@ -27752,6 +27753,92 @@ printf "%s\n" "#define Py_NOGIL 1" >>confdefs.h fi +# gh-109054: Check if -latomic is needed to get atomic functions. +# On aarch64, GCC may require programs to be linked explicitly to libatomic. +# Use _Py_atomic_or_uint64() which may require libatomic __atomic_fetch_or_8() +# on Linux aarch64 (or not depending on the compiler and the compiler flags). +# +# Avoid #include or #include . The header +# requires header which is only written below by AC_OUTPUT below. +# If the check is done after AC_OUTPUT, modifying LIBS has no effect anymore. +# cannot be included alone, it's designed to be included by +# : it expects other includes and macros to be defined. + +LIBATOMIC="" + +save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="${BASECPPFLAGS} -I. -I${srcdir}/Include ${CPPFLAGS}" + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether libatomic is needed by " >&5 +printf %s "checking whether libatomic is needed by ... " >&6; } +if test ${ac_cv_libatomic_needed+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test "$cross_compiling" = yes +then : + ac_cv_libatomic_needed=yes +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +// pyatomic.h needs uint64_t and Py_ssize_t types +#include // int64_t, intptr_t +#ifdef HAVE_SYS_TYPES_H +# include // ssize_t +#endif +// Code adapted from Include/pyport.h +#if HAVE_SSIZE_T +typedef ssize_t Py_ssize_t; +#elif SIZEOF_VOID_P == SIZEOF_SIZE_T +typedef intptr_t Py_ssize_t; +#else +# error "unable to find a type fitting ssize_t" +#endif + +#include "cpython/pyatomic.h" + +int main() +{ + // use _Py_atomic_or_uint64() which requires libatomic __atomic_fetch_or_8() + // on Linux aarch64. + uint64_t byte; + _Py_atomic_store_uint64(&byte, 2); + if (_Py_atomic_or_uint64(&byte, 8) != 2) { + return 1; // error + } + if (_Py_atomic_load_uint64(&byte) != 10) { + return 1; // error + } + return 0; // all good +} + +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + + ac_cv_libatomic_needed=no + +else $as_nop + ac_cv_libatomic_needed=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libatomic_needed" >&5 +printf "%s\n" "$ac_cv_libatomic_needed" >&6; } + +if test $ac_cv_libatomic_needed = yes +then + LIBATOMIC="-latomic" +fi +CPPFLAGS=$save_CPPFLAGS + + +# stdlib # stdlib not available @@ -29900,7 +29987,7 @@ fi then : - + as_fn_append MODULE_BLOCK "MODULE__TESTCAPI_LDFLAGS=$LIBATOMIC$as_nl" fi if test "$py_cv_module__testcapi" = yes; then @@ -30344,6 +30431,7 @@ ac_config_files="$ac_config_files Modules/Setup.bootstrap Modules/Setup.stdlib" ac_config_files="$ac_config_files Modules/ld_so_aix" +# Generate files like pyconfig.h cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure diff --git a/configure.ac b/configure.ac index 612c072af329d46..c1796d6d402d2f8 100644 --- a/configure.ac +++ b/configure.ac @@ -6962,6 +6962,68 @@ then [Define if you want to disable the GIL]) fi +# gh-109054: Check if -latomic is needed to get atomic functions. +# On aarch64, GCC may require programs to be linked explicitly to libatomic. +# Use _Py_atomic_or_uint64() which may require libatomic __atomic_fetch_or_8() +# on Linux aarch64 (or not depending on the compiler and the compiler flags). +# +# Avoid #include or #include . The header +# requires header which is only written below by AC_OUTPUT below. +# If the check is done after AC_OUTPUT, modifying LIBS has no effect anymore. +# cannot be included alone, it's designed to be included by +# : it expects other includes and macros to be defined. +AC_SUBST([LIBATOMIC]) +LIBATOMIC="" + +_SAVE_VAR([CPPFLAGS]) +CPPFLAGS="${BASECPPFLAGS} -I. -I${srcdir}/Include ${CPPFLAGS}" + +AC_CACHE_CHECK([whether libatomic is needed by ], + [ac_cv_libatomic_needed], +[AC_RUN_IFELSE([AC_LANG_SOURCE([[ +// pyatomic.h needs uint64_t and Py_ssize_t types +#include // int64_t, intptr_t +#ifdef HAVE_SYS_TYPES_H +# include // ssize_t +#endif +// Code adapted from Include/pyport.h +#if HAVE_SSIZE_T +typedef ssize_t Py_ssize_t; +#elif SIZEOF_VOID_P == SIZEOF_SIZE_T +typedef intptr_t Py_ssize_t; +#else +# error "unable to find a type fitting ssize_t" +#endif + +#include "cpython/pyatomic.h" + +int main() +{ + // use _Py_atomic_or_uint64() which requires libatomic __atomic_fetch_or_8() + // on Linux aarch64. + uint64_t byte; + _Py_atomic_store_uint64(&byte, 2); + if (_Py_atomic_or_uint64(&byte, 8) != 2) { + return 1; // error + } + if (_Py_atomic_load_uint64(&byte) != 10) { + return 1; // error + } + return 0; // all good +} +]])],[ + ac_cv_libatomic_needed=no +],[ac_cv_libatomic_needed=yes],[ac_cv_libatomic_needed=yes]) +]) + +if test $ac_cv_libatomic_needed = yes +then + LIBATOMIC="-latomic" +fi +_RESTORE_VAR([CPPFLAGS]) + + +# stdlib AC_DEFUN([PY_STDLIB_MOD_SET_NA], [ m4_foreach([mod], [$@], [ AS_VAR_SET([py_cv_module_]mod, [n/a])]) @@ -7229,7 +7291,10 @@ PY_STDLIB_MOD([_hashlib], [], [test "$ac_cv_working_openssl_hashlib" = yes], [$OPENSSL_INCLUDES], [$OPENSSL_LDFLAGS $OPENSSL_LDFLAGS_RPATH $LIBCRYPTO_LIBS]) dnl test modules -PY_STDLIB_MOD([_testcapi], [test "$TEST_MODULES" = yes]) +PY_STDLIB_MOD([_testcapi], + [test "$TEST_MODULES" = yes], [] + dnl Modules/_testcapi/pyatomic.c uses header + [], [], [$LIBATOMIC]) PY_STDLIB_MOD([_testclinic], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testclinic_limited], [test "$TEST_MODULES" = yes]) PY_STDLIB_MOD([_testinternalcapi], [test "$TEST_MODULES" = yes]) @@ -7262,6 +7327,7 @@ AC_CONFIG_FILES(m4_normalize([ Modules/Setup.stdlib ])) AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix]) +# Generate files like pyconfig.h AC_OUTPUT AC_MSG_NOTICE([creating Modules/Setup.local])