gh-109054: configure checks if libatomic is needed (#109101)

Fix building the _testcapi extension on Linux AArch64 which requires
linking to libatomic when <cpython/pyatomic.h> 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
<cpython/pyatomic.h>.

Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
This commit is contained in:
Victor Stinner 2023-09-08 23:14:33 +02:00 committed by GitHub
parent 697c9dcf8f
commit 1f7e42131d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 151 additions and 2 deletions

View file

@ -0,0 +1,6 @@
Fix building the ``_testcapi`` extension on Linux AArch64 which requires
linking to libatomic when ``<cpython/pyatomic.h>`` 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.

85
configure generated vendored
View file

@ -27752,6 +27752,88 @@ printf "%s\n" "#define Py_NOGIL 1" >>confdefs.h
fi
# gh-109054: Check if -latomic is needed to get <pyatomic.h> atomic functions.
# On Linux aarch64, GCC may require programs and libraries to be linked
# explicitly to libatomic. Call _Py_atomic_or_uint64() which may require
# libatomic __atomic_fetch_or_8(), or not, depending on the C compiler and the
# compiler flags.
#
# Avoid #include <Python.h> or #include <pyport.h>. The <Python.h> header
# requires <pyconfig.h> header which is only written below by AC_OUTPUT below.
# If the check is done after AC_OUTPUT, modifying LIBATOMIC has no effect
# anymore. <pyport.h> cannot be included alone, it's designed to be included
# by <Python.h>: it expects other includes and macros to be defined.
save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="${BASECPPFLAGS} -I. -I${srcdir}/Include ${CPPFLAGS}"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether libatomic is needed by <pyatomic.h>" >&5
printf %s "checking whether libatomic is needed by <pyatomic.h>... " >&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 <stdint.h> // int64_t, intptr_t
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h> // 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 define Py_ssize_t"
#endif
#include "cpython/pyatomic.h"
int main()
{
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 "x$ac_cv_libatomic_needed" = xyes
then :
LIBATOMIC=${LIBATOMIC-"-latomic"}
fi
CPPFLAGS=$save_CPPFLAGS
# stdlib
# stdlib not available
@ -29900,7 +29982,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 +30426,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

View file

@ -6962,6 +6962,62 @@ then
[Define if you want to disable the GIL])
fi
# gh-109054: Check if -latomic is needed to get <pyatomic.h> atomic functions.
# On Linux aarch64, GCC may require programs and libraries to be linked
# explicitly to libatomic. Call _Py_atomic_or_uint64() which may require
# libatomic __atomic_fetch_or_8(), or not, depending on the C compiler and the
# compiler flags.
#
# Avoid #include <Python.h> or #include <pyport.h>. The <Python.h> header
# requires <pyconfig.h> header which is only written below by AC_OUTPUT below.
# If the check is done after AC_OUTPUT, modifying LIBATOMIC has no effect
# anymore. <pyport.h> cannot be included alone, it's designed to be included
# by <Python.h>: it expects other includes and macros to be defined.
_SAVE_VAR([CPPFLAGS])
CPPFLAGS="${BASECPPFLAGS} -I. -I${srcdir}/Include ${CPPFLAGS}"
AC_CACHE_CHECK([whether libatomic is needed by <pyatomic.h>],
[ac_cv_libatomic_needed],
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
// pyatomic.h needs uint64_t and Py_ssize_t types
#include <stdint.h> // int64_t, intptr_t
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h> // 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 define Py_ssize_t"
#endif
#include "cpython/pyatomic.h"
int main()
{
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])
])
AS_VAR_IF([ac_cv_libatomic_needed], [yes],
[LIBATOMIC=${LIBATOMIC-"-latomic"}])
_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 +7285,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 <cpython/pyatomic.h> 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 +7321,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])