From 0a9f69539be27acf1cddf1b58d02a88d02e5008d Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 10 Nov 2021 21:26:55 +0200 Subject: [PATCH] bpo-45747: Detect gdbm/dbm dependencies in configure (GH-29467) Co-authored-by: Erlend Egeberg Aasland --- Doc/whatsnew/3.11.rst | 4 + .../2021-11-08-11-31-48.bpo-45747.AODmk_.rst | 1 + Modules/Setup | 2 +- Modules/_dbmmodule.c | 32 +- configure | 339 +++++++++++++++++- configure.ac | 73 +++- pyconfig.h.in | 27 ++ setup.py | 281 ++------------- 8 files changed, 497 insertions(+), 262 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2021-11-08-11-31-48.bpo-45747.AODmk_.rst diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 27062f6162a..c0a6ce4c35a 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -528,6 +528,10 @@ Build Changes detected by :program:`configure`. (Contributed by Christian Heimes in :issue:`45763`.) +* Build dependencies for :mod:`dbm` are now detected by :program:`configure`. + ``libdb`` 3.x and 4.x are no longer supported. + (Contributed by Christian Heimes in :issue:`45747`.) + C API Changes ============= diff --git a/Misc/NEWS.d/next/Build/2021-11-08-11-31-48.bpo-45747.AODmk_.rst b/Misc/NEWS.d/next/Build/2021-11-08-11-31-48.bpo-45747.AODmk_.rst new file mode 100644 index 00000000000..f60b83fd5af --- /dev/null +++ b/Misc/NEWS.d/next/Build/2021-11-08-11-31-48.bpo-45747.AODmk_.rst @@ -0,0 +1 @@ +gdbm and dbm build dependencies are now detected by ``configure``. diff --git a/Modules/Setup b/Modules/Setup index 57584f38fd8..49c69031216 100644 --- a/Modules/Setup +++ b/Modules/Setup @@ -216,7 +216,7 @@ time timemodule.c #_bz2 _bz2module.c -lbz2 #_ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c -ldl -lffi -DHAVE_FFI_PREP_CIF_VAR -DHAVE_FFI_PREP_CLOSURE_LOC -DHAVE_FFI_CLOSURE_ALLOC # The _dbm module supports NDBM, GDBM with compat module, and Berkeley DB. -#_dbm _dbmmodule.c -lgdbm_compat -DHAVE_NDBM_H +#_dbm _dbmmodule.c -lgdbm_compat -DUSE_GDBM_COMPAT #_gdbm _gdbmmodule.c -lgdbm #_lzma _lzmamodule.c -llzma #_sqlite3 _sqlite/connection.c _sqlite/cursor.c _sqlite/microprotocols.c _sqlite/module.c _sqlite/prepare_protocol.c _sqlite/row.c _sqlite/statement.c _sqlite/util.c -lsqlite3 diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index 4cbbac3326a..c0371fb3f3b 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -12,20 +12,26 @@ /* Some Linux systems install gdbm/ndbm.h, but not ndbm.h. This supports * whichever configure was able to locate. */ -#if defined(HAVE_NDBM_H) -#include -static const char which_dbm[] = "GNU gdbm"; /* EMX port of GDBM */ -#elif defined(HAVE_GDBM_NDBM_H) -#include -static const char which_dbm[] = "GNU gdbm"; -#elif defined(HAVE_GDBM_DASH_NDBM_H) -#include -static const char which_dbm[] = "GNU gdbm"; -#elif defined(HAVE_BERKDB_H) -#include -static const char which_dbm[] = "Berkeley DB"; +#if defined(USE_NDBM) + #include + static const char which_dbm[] = "GNU gdbm"; /* EMX port of GDBM */ +#elif defined(USE_GDBM_COMPAT) + #ifdef HAVE_GDBM_NDBM_H + #include + #elif HAVE_GDBM_DASH_NDBM_H + #include + #else + #error "No gdbm/ndbm.h or gdbm-ndbm.h available" + #endif + static const char which_dbm[] = "GNU gdbm"; +#elif defined(USE_BERKDB) + #ifndef DB_DBM_HSEARCH + #define DB_DBM_HSEARCH 1 + #endif + #include + static const char which_dbm[] = "Berkeley DB"; #else -#error "No ndbm.h available!" + #error "No ndbm.h available!" #endif typedef struct { diff --git a/configure b/configure index d9c41226a35..2a89703d294 100755 --- a/configure +++ b/configure @@ -10822,6 +10822,340 @@ else TCLTK_LIBS="$with_tcltk_libs" fi +# check for _gdbmmodulec dependencies +for ac_header in gdbm.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "gdbm.h" "ac_cv_header_gdbm_h" "$ac_includes_default" +if test "x$ac_cv_header_gdbm_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GDBM_H 1 +_ACEOF + + LIBS_SAVE=$LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdbm_open in -lgdbm" >&5 +$as_echo_n "checking for gdbm_open in -lgdbm... " >&6; } +if ${ac_cv_lib_gdbm_gdbm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgdbm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gdbm_open (); +int +main () +{ +return gdbm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gdbm_gdbm_open=yes +else + ac_cv_lib_gdbm_gdbm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_gdbm_open" >&5 +$as_echo "$ac_cv_lib_gdbm_gdbm_open" >&6; } +if test "x$ac_cv_lib_gdbm_gdbm_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGDBM 1 +_ACEOF + + LIBS="-lgdbm $LIBS" + +fi + + LIBS=$LIBS_SAVE + +fi + +done + + +# check for _dbmmodule.c dependencies +for ac_header in ndbm.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "ndbm.h" "ac_cv_header_ndbm_h" "$ac_includes_default" +if test "x$ac_cv_header_ndbm_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NDBM_H 1 +_ACEOF + + LIBS_SAVE="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm_open in -lndbm" >&5 +$as_echo_n "checking for dbm_open in -lndbm... " >&6; } +if ${ac_cv_lib_ndbm_dbm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lndbm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dbm_open (); +int +main () +{ +return dbm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ndbm_dbm_open=yes +else + ac_cv_lib_ndbm_dbm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ndbm_dbm_open" >&5 +$as_echo "$ac_cv_lib_ndbm_dbm_open" >&6; } +if test "x$ac_cv_lib_ndbm_dbm_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNDBM 1 +_ACEOF + + LIBS="-lndbm $LIBS" + +fi + + LIBS="$LIBS_SAVE" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm_open in -lgdbm_compat" >&5 +$as_echo_n "checking for dbm_open in -lgdbm_compat... " >&6; } +if ${ac_cv_lib_gdbm_compat_dbm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgdbm_compat $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dbm_open (); +int +main () +{ +return dbm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gdbm_compat_dbm_open=yes +else + ac_cv_lib_gdbm_compat_dbm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_compat_dbm_open" >&5 +$as_echo "$ac_cv_lib_gdbm_compat_dbm_open" >&6; } +if test "x$ac_cv_lib_gdbm_compat_dbm_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGDBM_COMPAT 1 +_ACEOF + + LIBS="-lgdbm_compat $LIBS" + +fi + + LIBS="$LIBS_SAVE" + +fi + +done + + +# "gdbm-ndbm.h" and "gdbm/ndbm.h" are both normalized to "gdbm_ndbm_h" +# unset ac_cv_header_gdbm_ndbm_h to prevent false positive cache hits. +{ ac_cv_header_gdbm_ndbm_h=; unset ac_cv_header_gdbm_ndbm_h;} +if ${ac_cv_header_gdbm_slash_ndbm_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_fn_c_check_header_mongrel "$LINENO" "gdbm/ndbm.h" "ac_cv_header_gdbm_ndbm_h" "$ac_includes_default" +if test "x$ac_cv_header_gdbm_ndbm_h" = xyes; then : + ac_cv_header_gdbm_slash_ndbm_h=yes +else + ac_cv_header_gdbm_slash_ndbm_h=no + +fi + + + +fi + +if test "x$ac_cv_header_gdbm_slash_ndbm_h" = xyes; then : + + +$as_echo "#define HAVE_GDBM_NDBM_H 1" >>confdefs.h + + +fi + +{ ac_cv_header_gdbm_ndbm_h=; unset ac_cv_header_gdbm_ndbm_h;} +if ${ac_cv_header_gdbm_dash_ndbm_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ac_fn_c_check_header_mongrel "$LINENO" "gdbm-ndbm.h" "ac_cv_header_gdbm_ndbm_h" "$ac_includes_default" +if test "x$ac_cv_header_gdbm_ndbm_h" = xyes; then : + ac_cv_header_gdbm_dash_ndbm_h=yes +else + ac_cv_header_gdbm_dash_ndbm_h=no + +fi + + + +fi + +if test "x$ac_cv_header_gdbm_dash_ndbm_h" = xyes; then : + + +$as_echo "#define HAVE_GDBM_DASH_NDBM_H 1" >>confdefs.h + + +fi +{ ac_cv_header_gdbm_ndbm_h=; unset ac_cv_header_gdbm_ndbm_h;} + +if test "$ac_cv_header_gdbm_slash_ndbm_h" = yes -o "$ac_cv_header_gdbm_dash_ndbm_h" = yes; then + LIBS_SAVE="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm_open in -lgdbm_compat" >&5 +$as_echo_n "checking for dbm_open in -lgdbm_compat... " >&6; } +if ${ac_cv_lib_gdbm_compat_dbm_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgdbm_compat $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dbm_open (); +int +main () +{ +return dbm_open (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gdbm_compat_dbm_open=yes +else + ac_cv_lib_gdbm_compat_dbm_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gdbm_compat_dbm_open" >&5 +$as_echo "$ac_cv_lib_gdbm_compat_dbm_open" >&6; } +if test "x$ac_cv_lib_gdbm_compat_dbm_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGDBM_COMPAT 1 +_ACEOF + + LIBS="-lgdbm_compat $LIBS" + +fi + + LIBS="$LIBS_SAVE" +fi + +# Check for libdb >= 5 with dbm_open() +# db.h re-defines the name of the function +for ac_header in db.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "db.h" "ac_cv_header_db_h" "$ac_includes_default" +if test "x$ac_cv_header_db_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DB_H 1 +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libdb" >&5 +$as_echo_n "checking for libdb... " >&6; } +if ${ac_cv_have_libdb+:} false; then : + $as_echo_n "(cached) " >&6 +else + + LIBS_SAVE="$LIBS" + LIBS="$LIBS -ldb" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define DB_DBM_HSEARCH 1 + #include + #if DB_VERSION_MAJOR < 5 + #error "dh.h: DB_VERSION_MAJOR < 5 is not supported." + #endif + +int +main () +{ +DBM *dbm = dbm_open(NULL, 0, 0) + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_have_libdb=yes +else + ac_cv_have_libdb=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$LIBS_SAVE" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_libdb" >&5 +$as_echo "$ac_cv_have_libdb" >&6; } + if test "x$ac_cv_have_libdb" = xyes; then : + + +$as_echo "#define HAVE_LIBDB 1" >>confdefs.h + + +fi + +fi + +done + + # Check for --with-dbmliborder { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-dbmliborder" >&5 $as_echo_n "checking for --with-dbmliborder... " >&6; } @@ -10833,12 +11167,15 @@ if test x$with_dbmliborder = xyes then as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5 else - for db in `echo $with_dbmliborder | sed 's/:/ /g'`; do + as_save_IFS=$IFS + IFS=: + for db in $with_dbmliborder; do if test x$db != xndbm && test x$db != xgdbm && test x$db != xbdb then as_fn_error $? "proper usage is --with-dbmliborder=db1:db2:..." "$LINENO" 5 fi done + IFS=$as_save_IFS fi fi diff --git a/configure.ac b/configure.ac index cfd7184ac3a..4817422178d 100644 --- a/configure.ac +++ b/configure.ac @@ -3094,6 +3094,74 @@ else TCLTK_LIBS="$with_tcltk_libs" fi +# check for _gdbmmodulec dependencies +AC_CHECK_HEADERS([gdbm.h], [ + LIBS_SAVE=$LIBS + AC_CHECK_LIB([gdbm], [gdbm_open]) + LIBS=$LIBS_SAVE +]) + +# check for _dbmmodule.c dependencies +AC_CHECK_HEADERS([ndbm.h], [ + LIBS_SAVE="$LIBS" + AC_CHECK_LIB([ndbm], [dbm_open]) + LIBS="$LIBS_SAVE" + AC_CHECK_LIB([gdbm_compat], [dbm_open]) + LIBS="$LIBS_SAVE" +]) + +# "gdbm-ndbm.h" and "gdbm/ndbm.h" are both normalized to "gdbm_ndbm_h" +# unset ac_cv_header_gdbm_ndbm_h to prevent false positive cache hits. +AS_UNSET([ac_cv_header_gdbm_ndbm_h]) +AC_CACHE_VAL([ac_cv_header_gdbm_slash_ndbm_h], [ + AC_CHECK_HEADER( + [gdbm/ndbm.h], + [ac_cv_header_gdbm_slash_ndbm_h=yes], [ac_cv_header_gdbm_slash_ndbm_h=no] + ) +]) +AS_VAR_IF([ac_cv_header_gdbm_slash_ndbm_h], [yes], [ + AC_DEFINE([HAVE_GDBM_NDBM_H], [1], [Define to 1 if you have the header file.]) +]) + +AS_UNSET([ac_cv_header_gdbm_ndbm_h]) +AC_CACHE_VAL([ac_cv_header_gdbm_dash_ndbm_h], [ + AC_CHECK_HEADER( + [gdbm-ndbm.h], + [ac_cv_header_gdbm_dash_ndbm_h=yes], [ac_cv_header_gdbm_dash_ndbm_h=no] + ) +]) +AS_VAR_IF([ac_cv_header_gdbm_dash_ndbm_h], [yes], [ + AC_DEFINE([HAVE_GDBM_DASH_NDBM_H], [1], [Define to 1 if you have the header file.]) +]) +AS_UNSET([ac_cv_header_gdbm_ndbm_h]) + +if test "$ac_cv_header_gdbm_slash_ndbm_h" = yes -o "$ac_cv_header_gdbm_dash_ndbm_h" = yes; then + LIBS_SAVE="$LIBS" + AC_CHECK_LIB([gdbm_compat], [dbm_open]) + LIBS="$LIBS_SAVE" +fi + +# Check for libdb >= 5 with dbm_open() +# db.h re-defines the name of the function +AC_CHECK_HEADERS([db.h], [ + AC_CACHE_CHECK([for libdb], [ac_cv_have_libdb], [ + LIBS_SAVE="$LIBS" + LIBS="$LIBS -ldb" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + #define DB_DBM_HSEARCH 1 + #include + #if DB_VERSION_MAJOR < 5 + #error "dh.h: DB_VERSION_MAJOR < 5 is not supported." + #endif + ], [DBM *dbm = dbm_open(NULL, 0, 0)]) + ], [ac_cv_have_libdb=yes], [ac_cv_have_libdb=no]) + LIBS="$LIBS_SAVE" + ]) + AS_VAR_IF([ac_cv_have_libdb], [yes], [ + AC_DEFINE([HAVE_LIBDB], [1], [Define to 1 if you have the `db' library (-ldb).]) + ]) +]) + # Check for --with-dbmliborder AC_MSG_CHECKING(for --with-dbmliborder) AC_ARG_WITH(dbmliborder, @@ -3103,12 +3171,15 @@ if test x$with_dbmliborder = xyes then AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:...]) else - for db in `echo $with_dbmliborder | sed 's/:/ /g'`; do + as_save_IFS=$IFS + IFS=: + for db in $with_dbmliborder; do if test x$db != xndbm && test x$db != xgdbm && test x$db != xbdb then AC_MSG_ERROR([proper usage is --with-dbmliborder=db1:db2:...]) fi done + IFS=$as_save_IFS fi]) AC_MSG_RESULT($with_dbmliborder) diff --git a/pyconfig.h.in b/pyconfig.h.in index 2f71dd1758d..cbab59b739f 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -214,6 +214,9 @@ /* Define if you have the 'wchgat' function. */ #undef HAVE_CURSES_WCHGAT +/* Define to 1 if you have the header file. */ +#undef HAVE_DB_H + /* Define to 1 if you have the declaration of `RTLD_DEEPBIND', and to 0 if you don't. */ #undef HAVE_DECL_RTLD_DEEPBIND @@ -420,6 +423,15 @@ /* Define if your compiler provides __uint128_t */ #undef HAVE_GCC_UINT128_T +/* Define to 1 if you have the header file. */ +#undef HAVE_GDBM_DASH_NDBM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GDBM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GDBM_NDBM_H + /* Define if you have the getaddrinfo function. */ #undef HAVE_GETADDRINFO @@ -586,12 +598,21 @@ /* Define to 1 if you have the `bz2' library (-lbz2). */ #undef HAVE_LIBBZ2 +/* Define to 1 if you have the `db' library (-ldb). */ +#undef HAVE_LIBDB + /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `dld' library (-ldld). */ #undef HAVE_LIBDLD +/* Define to 1 if you have the `gdbm' library (-lgdbm). */ +#undef HAVE_LIBGDBM + +/* Define to 1 if you have the `gdbm_compat' library (-lgdbm_compat). */ +#undef HAVE_LIBGDBM_COMPAT + /* Define to 1 if you have the `ieee' library (-lieee). */ #undef HAVE_LIBIEEE @@ -601,6 +622,9 @@ /* Define to 1 if you have the `lzma' library (-llzma). */ #undef HAVE_LIBLZMA +/* Define to 1 if you have the `ndbm' library (-lndbm). */ +#undef HAVE_LIBNDBM + /* Define to build the readline module. */ #undef HAVE_LIBREADLINE @@ -733,6 +757,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NCURSES_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NDBM_H + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H diff --git a/setup.py b/setup.py index 7fe7d27b14c..771ab565631 100644 --- a/setup.py +++ b/setup.py @@ -1221,208 +1221,19 @@ def detect_dbm_gdbm(self): # implementation independent wrapper for these; dbm/dumb.py provides # similar functionality (but slower of course) implemented in Python. - # Sleepycat^WOracle Berkeley DB interface. - # https://www.oracle.com/database/technologies/related/berkeleydb.html - # - # This requires the Sleepycat^WOracle DB code. The supported versions - # are set below. Visit the URL above to download - # a release. Most open source OSes come with one or more - # versions of BerkeleyDB already installed. - - max_db_ver = (5, 3) - min_db_ver = (3, 3) - db_setup_debug = False # verbose debug prints from this script? - - def allow_db_ver(db_ver): - """Returns a boolean if the given BerkeleyDB version is acceptable. - - Args: - db_ver: A tuple of the version to verify. - """ - if not (min_db_ver <= db_ver <= max_db_ver): - return False - return True - - def gen_db_minor_ver_nums(major): - if major == 4: - for x in range(max_db_ver[1]+1): - if allow_db_ver((4, x)): - yield x - elif major == 3: - for x in (3,): - if allow_db_ver((3, x)): - yield x - else: - raise ValueError("unknown major BerkeleyDB version", major) - - # construct a list of paths to look for the header file in on - # top of the normal inc_dirs. - db_inc_paths = [ - '/usr/include/db4', - '/usr/local/include/db4', - '/opt/sfw/include/db4', - '/usr/include/db3', - '/usr/local/include/db3', - '/opt/sfw/include/db3', - # Fink defaults (https://www.finkproject.org/) - '/sw/include/db4', - '/sw/include/db3', - ] - # 4.x minor number specific paths - for x in gen_db_minor_ver_nums(4): - db_inc_paths.append('/usr/include/db4%d' % x) - db_inc_paths.append('/usr/include/db4.%d' % x) - db_inc_paths.append('/usr/local/BerkeleyDB.4.%d/include' % x) - db_inc_paths.append('/usr/local/include/db4%d' % x) - db_inc_paths.append('/pkg/db-4.%d/include' % x) - db_inc_paths.append('/opt/db-4.%d/include' % x) - # MacPorts default (https://www.macports.org/) - db_inc_paths.append('/opt/local/include/db4%d' % x) - # 3.x minor number specific paths - for x in gen_db_minor_ver_nums(3): - db_inc_paths.append('/usr/include/db3%d' % x) - db_inc_paths.append('/usr/local/BerkeleyDB.3.%d/include' % x) - db_inc_paths.append('/usr/local/include/db3%d' % x) - db_inc_paths.append('/pkg/db-3.%d/include' % x) - db_inc_paths.append('/opt/db-3.%d/include' % x) - - if CROSS_COMPILING: - db_inc_paths = [] - - # Add some common subdirectories for Sleepycat DB to the list, - # based on the standard include directories. This way DB3/4 gets - # picked up when it is installed in a non-standard prefix and - # the user has added that prefix into inc_dirs. - std_variants = [] - for dn in self.inc_dirs: - std_variants.append(os.path.join(dn, 'db3')) - std_variants.append(os.path.join(dn, 'db4')) - for x in gen_db_minor_ver_nums(4): - std_variants.append(os.path.join(dn, "db4%d"%x)) - std_variants.append(os.path.join(dn, "db4.%d"%x)) - for x in gen_db_minor_ver_nums(3): - std_variants.append(os.path.join(dn, "db3%d"%x)) - std_variants.append(os.path.join(dn, "db3.%d"%x)) - - db_inc_paths = std_variants + db_inc_paths - db_inc_paths = [p for p in db_inc_paths if os.path.exists(p)] - - db_ver_inc_map = {} - - if MACOS: - sysroot = macosx_sdk_root() - - class db_found(Exception): pass - try: - # See whether there is a Sleepycat header in the standard - # search path. - for d in self.inc_dirs + db_inc_paths: - f = os.path.join(d, "db.h") - if MACOS and is_macosx_sdk_path(d): - f = os.path.join(sysroot, d[1:], "db.h") - - if db_setup_debug: print("db: looking for db.h in", f) - if os.path.exists(f): - with open(f, 'rb') as file: - f = file.read() - m = re.search(br"#define\WDB_VERSION_MAJOR\W(\d+)", f) - if m: - db_major = int(m.group(1)) - m = re.search(br"#define\WDB_VERSION_MINOR\W(\d+)", f) - db_minor = int(m.group(1)) - db_ver = (db_major, db_minor) - - # Avoid 4.6 prior to 4.6.21 due to a BerkeleyDB bug - if db_ver == (4, 6): - m = re.search(br"#define\WDB_VERSION_PATCH\W(\d+)", f) - db_patch = int(m.group(1)) - if db_patch < 21: - print("db.h:", db_ver, "patch", db_patch, - "being ignored (4.6.x must be >= 4.6.21)") - continue - - if ( (db_ver not in db_ver_inc_map) and - allow_db_ver(db_ver) ): - # save the include directory with the db.h version - # (first occurrence only) - db_ver_inc_map[db_ver] = d - if db_setup_debug: - print("db.h: found", db_ver, "in", d) - else: - # we already found a header for this library version - if db_setup_debug: print("db.h: ignoring", d) - else: - # ignore this header, it didn't contain a version number - if db_setup_debug: - print("db.h: no version number version in", d) - - db_found_vers = list(db_ver_inc_map.keys()) - db_found_vers.sort() - - while db_found_vers: - db_ver = db_found_vers.pop() - db_incdir = db_ver_inc_map[db_ver] - - # check lib directories parallel to the location of the header - db_dirs_to_check = [ - db_incdir.replace("include", 'lib64'), - db_incdir.replace("include", 'lib'), - ] - - if not MACOS: - db_dirs_to_check = list(filter(os.path.isdir, db_dirs_to_check)) - - else: - # Same as other branch, but takes OSX SDK into account - tmp = [] - for dn in db_dirs_to_check: - if is_macosx_sdk_path(dn): - if os.path.isdir(os.path.join(sysroot, dn[1:])): - tmp.append(dn) - else: - if os.path.isdir(dn): - tmp.append(dn) - db_dirs_to_check = tmp - - db_dirs_to_check = tmp - - # Look for a version specific db-X.Y before an ambiguous dbX - # XXX should we -ever- look for a dbX name? Do any - # systems really not name their library by version and - # symlink to more general names? - for dblib in (('db-%d.%d' % db_ver), - ('db%d%d' % db_ver), - ('db%d' % db_ver[0])): - dblib_file = self.compiler.find_library_file( - db_dirs_to_check + self.lib_dirs, dblib ) - if dblib_file: - dblib_dir = [ os.path.abspath(os.path.dirname(dblib_file)) ] - raise db_found - else: - if db_setup_debug: print("db lib: ", dblib, "not found") - - except db_found: - if db_setup_debug: - print("bsddb using BerkeleyDB lib:", db_ver, dblib) - print("bsddb lib dir:", dblib_dir, " inc dir:", db_incdir) - dblibs = [dblib] - # Only add the found library and include directories if they aren't - # already being searched. This avoids an explicit runtime library - # dependency. - if db_incdir in self.inc_dirs: - db_incs = None - else: - db_incs = [db_incdir] - if dblib_dir[0] in self.lib_dirs: - dblib_dir = None - else: - if db_setup_debug: print("db: no appropriate library found") - db_incs = None - dblibs = [] - dblib_dir = None - dbm_setup_debug = False # verbose debug prints from this script? dbm_order = ['gdbm'] + + # libdb, gdbm and ndbm headers and libraries + have_ndbm_h = sysconfig.get_config_var("HAVE_NDBM_H") + have_gdbm_h = sysconfig.get_config_var("HAVE_GDBM_H") + have_gdbm_ndbm_h = sysconfig.get_config_var("HAVE_GDBM_NDBM_H") + have_gdbm_dash_ndbm_h = sysconfig.get_config_var("HAVE_GDBM_DASH_NDBM_H") + have_libndbm = sysconfig.get_config_var("HAVE_LIBNDBM") + have_libgdbm = sysconfig.get_config_var("HAVE_LIBGDBM") + have_libgdbm_compat = sysconfig.get_config_var("HAVE_LIBGDBM_COMPAT") + have_libdb = sysconfig.get_config_var("HAVE_LIBDB") + # The standard Unix dbm module: if not CYGWIN: config_args = [arg.strip("'") @@ -1436,61 +1247,40 @@ class db_found(Exception): pass dbmext = None for cand in dbm_order: if cand == "ndbm": - if find_file("ndbm.h", self.inc_dirs, []) is not None: + if have_ndbm_h: # Some systems have -lndbm, others have -lgdbm_compat, # others don't have either - if self.compiler.find_library_file(self.lib_dirs, - 'ndbm'): + if have_libndbm: ndbm_libs = ['ndbm'] - elif self.compiler.find_library_file(self.lib_dirs, - 'gdbm_compat'): + elif have_libgdbm_compat: ndbm_libs = ['gdbm_compat'] else: ndbm_libs = [] if dbm_setup_debug: print("building dbm using ndbm") - dbmext = Extension('_dbm', ['_dbmmodule.c'], - define_macros=[ - ('HAVE_NDBM_H',None), - ], - libraries=ndbm_libs) + dbmext = Extension( + '_dbm', ['_dbmmodule.c'], + define_macros=[('USE_NDBM', None)], + libraries=ndbm_libs + ) break - elif cand == "gdbm": - if self.compiler.find_library_file(self.lib_dirs, 'gdbm'): - gdbm_libs = ['gdbm'] - if self.compiler.find_library_file(self.lib_dirs, - 'gdbm_compat'): - gdbm_libs.append('gdbm_compat') - if find_file("gdbm/ndbm.h", self.inc_dirs, []) is not None: - if dbm_setup_debug: print("building dbm using gdbm") - dbmext = Extension( - '_dbm', ['_dbmmodule.c'], - define_macros=[ - ('HAVE_GDBM_NDBM_H', None), - ], - libraries = gdbm_libs) - break - if find_file("gdbm-ndbm.h", self.inc_dirs, []) is not None: - if dbm_setup_debug: print("building dbm using gdbm") - dbmext = Extension( - '_dbm', ['_dbmmodule.c'], - define_macros=[ - ('HAVE_GDBM_DASH_NDBM_H', None), - ], - libraries = gdbm_libs) - break + # dbm_open() is provided by libgdbm_compat, which wraps libgdbm + if have_libgdbm_compat and (have_gdbm_ndbm_h or have_gdbm_dash_ndbm_h): + if dbm_setup_debug: print("building dbm using gdbm") + dbmext = Extension( + '_dbm', ['_dbmmodule.c'], + define_macros=[('USE_GDBM_COMPAT', None)], + libraries=['gdbm_compat'] + ) + break elif cand == "bdb": - if dblibs: + if have_libdb: if dbm_setup_debug: print("building dbm using bdb") - dbmext = Extension('_dbm', ['_dbmmodule.c'], - library_dirs=dblib_dir, - runtime_library_dirs=dblib_dir, - include_dirs=db_incs, - define_macros=[ - ('HAVE_BERKDB_H', None), - ('DB_DBM_HSEARCH', None), - ], - libraries=dblibs) + dbmext = Extension( + '_dbm', ['_dbmmodule.c'], + define_macros=[('USE_BERKDB', None)], + libraries=['db'] + ) break if dbmext is not None: self.add(dbmext) @@ -1498,8 +1288,7 @@ class db_found(Exception): pass self.missing.append('_dbm') # Anthony Baxter's gdbm module. GNU dbm(3) will require -lgdbm: - if ('gdbm' in dbm_order and - self.compiler.find_library_file(self.lib_dirs, 'gdbm')): + if 'gdbm' in dbm_order and have_libgdbm: self.add(Extension('_gdbm', ['_gdbmmodule.c'], libraries=['gdbm'])) else: