From 64586d56a0214b4c709c987d2e03f21f31fb6feb Mon Sep 17 00:00:00 2001 From: Dana Robinson Date: Wed, 20 Mar 2024 03:15:20 -0700 Subject: [PATCH 1/2] Fixes several MinGW + Autotools issues * Fixes detection of various Windows libraries, etc. * Corrects alarm(2) configure checks * Uses Win32 threads by default w/ Pthreads override, if desired * Set _WIN32_WINNT correctly for MinGW * Fix setenv(3) wrapper for MinGW, which does not have getenv_s() MinGW Autotools support is still not Amazing, but this at least allows the library and tools build and is better about thread-safety --- config/cmake/H5pubconf.h.in | 4 +- configure.ac | 227 ++++++++++++++++++++---------------- src/H5private.h | 8 ++ src/H5system.c | 9 +- test/testframe.c | 3 +- 5 files changed, 148 insertions(+), 103 deletions(-) diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in index af8948d9f6e..b3fbede50a3 100644 --- a/config/cmake/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in @@ -366,10 +366,10 @@ /* Define to 1 if you have the `waitpid' function. */ #cmakedefine H5_HAVE_WAITPID @H5_HAVE_WAITPID@ -/* Define to 1 if you have the 'InitOnceExecuteOnce' function. */ +/* Define to 1 if you have Win32 threads */ #cmakedefine H5_HAVE_WIN_THREADS @H5_HAVE_WIN_THREADS@ -/* Define if your system has window style path name. */ +/* Define if your system has Windows-style path name. */ #cmakedefine H5_HAVE_WINDOW_PATH @H5_HAVE_WINDOW_PATH@ /* Define to 1 if you have the header file. */ diff --git a/configure.ac b/configure.ac index f33fb8b87b9..2149bb2d76a 100644 --- a/configure.ac +++ b/configure.ac @@ -1544,10 +1544,10 @@ case $host_os in esac ## Windows -case "`uname`" in - MINGW*) +case "$host_os" in + *mingw*) # The Winsock library - AC_CHECK_LIB([ws2_32], [GetUserName]) + AC_CHECK_LIB([ws2_32], [htons]) ;; esac @@ -1562,9 +1562,9 @@ AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h sys/socket.h]) ## if test "X${enable_shared}" = "Xyes"; then AC_MSG_CHECKING([if libtool needs -no-undefined flag to build shared libraries]) - case "`uname`" in - CYGWIN*|MINGW*|AIX*) - ## Add in the -no-undefined flag to LDFLAGS for libtool. + case "$$host_os" in + *cygwin*|*mingw*|*aix*) + ## Add in the -no-undefined flag to LDFLAGS for libtool AC_MSG_RESULT([yes]) H5_LDFLAGS="$H5_LDFLAGS -no-undefined" ;; @@ -1583,7 +1583,7 @@ AC_SYS_LARGEFILE ## ---------------------------------------------------------------------- ## Add necessary defines for Linux Systems. ## -case "$host_cpu-$host_vendor-$host_os" in +case "$host_os" in *linux*) ## Add POSIX support on Linux systems, so defines ## __USE_POSIX, which is required to get the prototype for fdopen @@ -1613,6 +1613,7 @@ case "$host_cpu-$host_vendor-$host_os" in H5_CPPFLAGS="-D_GNU_SOURCE $H5_CPPFLAGS" ;; *mingw*) + HDF_MINGW="yes" AC_DEFINE([HAVE_WINDOWS], [1], [Define if this is a Windows machine]) AC_DEFINE([HAVE_WIN32_API], [1], [Define if on the Windows platform using the Win32 API]) AC_DEFINE([HAVE_MINGW], [1], [Define if using MinGW]) @@ -2026,101 +2027,118 @@ if test "X$THREADSAFE" = "Xyes"; then ## and/or a library path. If the library path is specified then it must ## be preceded by a comma. ## - ## Thread-safety in HDF5 only uses Pthreads via configure, so the - ## default is "check", though this only has an effect when - ## --enable-threadsafe is specified. + ## The default is to use Pthreads when building with the Autotools, unless + ## we're building w/ MinGW. AC_SUBST([HAVE_PTHREAD]) HAVE_PTHREAD=yes AC_ARG_WITH([pthread], [AS_HELP_STRING([--with-pthread=DIR], [Specify alternative path to Pthreads library when - thread-safe capability is built.])],, - [withval=check]) - - case "$withval" in - check | yes) - AC_CHECK_HEADERS([pthread.h],, [unset HAVE_PTHREAD]) - if test "x$HAVE_PTHREAD" = "xyes"; then - AC_CHECK_LIB([pthread], [pthread_self],, [unset HAVE_PTHREAD]) + thread-safe capability is built. Set this to + 'yes' or the location of Pthreads when building + with MinGW and you would rather use Pthreads + than Win32 threads.])],, + [withval=default]) + + ## If we're on MinGW, we want to use Win32 threads unless the builder + ## explicitly specifies --with-pthreads=(yes | path(s)) + mingw_use_win32_threads="no" + if test -n "$HDF_MINGW" -a "$HDF_MINGW" = "yes" ; then + # Default or no --> Win32 threads + if test "$withval" = "default" -o "$withval" = "no" ; then + mingw_use_win32_threads="yes" + unset HAVE_PTHREAD + AC_DEFINE([HAVE_WIN_THREADS], [1], [Define to 1 if you have win32 threads]) fi - ;; - no) - AC_MSG_ERROR([Must use Pthreads with thread safety]) - ;; - *) + fi + + if test "$mingw_use_win32_threads" = "no" ; then case "$withval" in - *,*) - pthread_inc="`echo $withval | cut -f1 -d,`" - pthread_lib="`echo $withval | cut -f2 -d, -s`" - ;; - *) - if test -n "$withval"; then - pthread_inc="$withval/include" - pthread_lib="$withval/lib" - fi - ;; + default | yes) + AC_CHECK_HEADERS([pthread.h],, [unset HAVE_PTHREAD]) + if test "x$HAVE_PTHREAD" = "xyes"; then + AC_CHECK_LIB([pthread], [pthread_self],, [unset HAVE_PTHREAD]) + fi + ;; + no) + AC_MSG_ERROR([Must use Pthreads with thread safety on non-Windows systems]) + ;; + *) + case "$withval" in + *,*) + pthread_inc="`echo $withval | cut -f1 -d,`" + pthread_lib="`echo $withval | cut -f2 -d, -s`" + ;; + *) + if test -n "$withval"; then + pthread_inc="$withval/include" + pthread_lib="$withval/lib" + fi + ;; + esac + + if test -n "$pthread_inc"; then + saved_CPPFLAGS="$CPPFLAGS" + saved_AM_CPPFLAGS="$AM_CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I$pthread_inc" + AM_CPPFLAGS="$AM_CPPFLAGS -I$pthread_inc" + AC_CHECK_HEADERS([pthread.h],, [CPPFLAGS="$saved_CPPFLAGS"; AM_CPPFLAGS="$saved_AM_CPPFLAGS"; unset HAVE_PTHREAD]) + else + AC_CHECK_HEADERS([pthread.h],, [unset HAVE_PTHREAD]) + fi + + if test "x$HAVE_PTHREAD" = "xyes"; then + if test -n "$pthread_lib"; then + saved_LDFLAGS="$LDFLAGS" + saved_AM_LDFLAGS="$AM_LDFLAGS" + LDFLAGS="$LDFLAGS -L$pthread_lib" + AM_LDFLAGS="$AM_LDFLAGS -L$pthread_lib" + AC_CHECK_LIB([pthread], [pthread_self],, + [LDFLAGS="$saved_LDFLAGS"; AM_LDFLAGS="$saved_AM_LDFLAGS"; unset HAVE_PTHREAD]) + else + AC_CHECK_LIB([pthread], [pthread_self],, [unset HAVE_PTHREAD]) + fi + fi + ;; esac - if test -n "$pthread_inc"; then - saved_CPPFLAGS="$CPPFLAGS" - saved_AM_CPPFLAGS="$AM_CPPFLAGS" - CPPFLAGS="$CPPFLAGS -I$pthread_inc" - AM_CPPFLAGS="$AM_CPPFLAGS -I$pthread_inc" - AC_CHECK_HEADERS([pthread.h],, [CPPFLAGS="$saved_CPPFLAGS"; AM_CPPFLAGS="$saved_AM_CPPFLAGS"; unset HAVE_PTHREAD]) + ## ---------------------------------------------------------------------- + ## Check if pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM) + ## is supported on this system + ## + ## Unfortunately, this probably needs to be an AC_RUN_IFELSE since + ## it's impossible to determine if PTHREAD_SCOPE_SYSTEM is + ## supported a priori. POSIX.1-2001 requires that a conformant + ## system need only support one of SYSTEM or PROCESS scopes. + ## + ## CROSS-COMPILING: Use a pessimistic 'no'. You can hand-hack the config + ## file if you know otherwise. + AC_MSG_CHECKING([Pthreads supports system scope]) + AC_CACHE_VAL([hdf5_cv_system_scope_threads], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM([ + #include + #include + ],[ + pthread_attr_t attribute; + int ret; + + pthread_attr_init(&attribute); + ret=pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); + exit(ret==0 ? 0 : 1); + ])] + , [hdf5_cv_system_scope_threads=yes], [hdf5_cv_system_scope_threads=no], [hdf5_cv_system_scope_threads=no])]) + + if test ${hdf5_cv_system_scope_threads} = "yes"; then + AC_DEFINE([SYSTEM_SCOPE_THREADS], [1], + [Define if your system supports pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM) call.]) + AC_MSG_RESULT([yes]) else - AC_CHECK_HEADERS([pthread.h],, [unset HAVE_PTHREAD]) + AC_MSG_RESULT([no]) + AC_MSG_NOTICE([Always 'no' if cross-compiling. Edit the config file if your platform supports pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM).]) fi - if test "x$HAVE_PTHREAD" = "xyes"; then - if test -n "$pthread_lib"; then - saved_LDFLAGS="$LDFLAGS" - saved_AM_LDFLAGS="$AM_LDFLAGS" - LDFLAGS="$LDFLAGS -L$pthread_lib" - AM_LDFLAGS="$AM_LDFLAGS -L$pthread_lib" - AC_CHECK_LIB([pthread], [pthread_self],, - [LDFLAGS="$saved_LDFLAGS"; AM_LDFLAGS="$saved_AM_LDFLAGS"; unset HAVE_PTHREAD]) - else - AC_CHECK_LIB([pthread], [pthread_self],, [unset HAVE_PTHREAD]) - fi - fi - ;; - esac - - ## ---------------------------------------------------------------------- - ## Check if pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM) - ## is supported on this system - ## - ## Unfortunately, this probably needs to be an AC_RUN_IFELSE since - ## it's impossible to determine if PTHREAD_SCOPE_SYSTEM is - ## supported a priori. POSIX.1-2001 requires that a conformant - ## system need only support one of SYSTEM or PROCESS scopes. - ## - ## CROSS-COMPILING: Use a pessimistic 'no'. You can hand-hack the config - ## file if you know otherwise. - AC_MSG_CHECKING([Pthreads supports system scope]) - AC_CACHE_VAL([hdf5_cv_system_scope_threads], - [AC_RUN_IFELSE( - [AC_LANG_PROGRAM([ - #include - #include - ],[ - pthread_attr_t attribute; - int ret; - - pthread_attr_init(&attribute); - ret=pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM); - exit(ret==0 ? 0 : 1); - ])] - , [hdf5_cv_system_scope_threads=yes], [hdf5_cv_system_scope_threads=no], [hdf5_cv_system_scope_threads=no])]) - - if test ${hdf5_cv_system_scope_threads} = "yes"; then - AC_DEFINE([SYSTEM_SCOPE_THREADS], [1], - [Define if your system supports pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM) call.]) - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_MSG_NOTICE([Always 'no' if cross-compiling. Edit the config file if your platform supports pthread_attr_setscope(&attribute, PTHREAD_SCOPE_SYSTEM).]) - fi -fi + fi # end of Pthreads checks +fi # end of threadsafe processing ## ---------------------------------------------------------------------- ## Check for MONOTONIC_TIMER support (used in clock_gettime). This has @@ -2147,8 +2165,8 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ## Check whether the global variable `timezone' is defined. AC_MSG_CHECKING([for global timezone variable]) -case "`uname`" in - CYGWIN*) +case "$host_cpu-$host_vendor-$host_os" in + *cygwin*) AC_MSG_RESULT([disabled in CYGWIN]) ;; *) @@ -2178,8 +2196,8 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ## How do we figure out the width of a tty in characters? ## AC_CHECK_FUNCS([_getvideoconfig gettextinfo]) -case "`uname`" in - CYGWIN*) +case "$host_cpu-$host_vendor-$host_os" in + *cygwin*) ;; *) AC_CHECK_FUNCS([GetConsoleScreenBufferInfo]) @@ -2226,12 +2244,23 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ## NOTE: clock_gettime may require linking to the rt or posix4 library ## so we'll search for it before calling AC_CHECK_FUNCS. AC_SEARCH_LIBS([clock_gettime], [rt posix4]) -AC_CHECK_FUNCS([alarm asprintf clock_gettime fcntl flock fork]) +AC_CHECK_FUNCS([asprintf clock_gettime fcntl flock fork]) AC_CHECK_FUNCS([gethostname getrusage gettimeofday]) AC_CHECK_FUNCS([rand_r random]) AC_CHECK_FUNCS([strcasestr strdup symlink]) AC_CHECK_FUNCS([tmpfile vasprintf waitpid]) +case "$host_os" in + *mingw*) + # alarm(2) support is spotty in MinGW, so assume it doesn't exist + # + # https://lists.gnu.org/archive/html/bug-gnulib/2013-03/msg00040.html + ;; + *) + AC_CHECK_FUNCS([alarm]) + ;; +esac + ## ---------------------------------------------------------------------- ## Check compiler characteristics ## @@ -3650,10 +3679,10 @@ fi ## AC_MSG_CHECKING([if the machine has window style path name]) -case "`uname`" in - MINGW*) +case "$host_os" in + *mingw*) AC_DEFINE([HAVE_WINDOW_PATH], [1], - [Define if your system has window style path name.]) + [Define if your system has Windows-style path name.]) AC_MSG_RESULT([yes]) ;; *) diff --git a/src/H5private.h b/src/H5private.h index 7ede97967de..8cee9586769 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -121,6 +121,14 @@ #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */ #define NOGDI /* Exclude Graphic Display Interface macros */ +/* InitOnceExecuteOnce() requires 0x0600 to work on MinGW w/ Win32 threads */ +#if defined(H5_HAVE_MINGW) && defined(H5_HAVE_THREADSAFE) +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif +#endif + #include #include /* For _getcwd() */ diff --git a/src/H5system.c b/src/H5system.c index 6057c6ff639..7c540e5bf6b 100644 --- a/src/H5system.c +++ b/src/H5system.c @@ -339,13 +339,20 @@ Wsetenv(const char *name, const char *value, int overwrite) * value is non-zero), then return an error code. */ if (!overwrite) { +#ifndef H5_HAVE_MINGW size_t bufsize; errno_t err; err = getenv_s(&bufsize, NULL, 0, name); if (err || bufsize) return (int)err; - } /* end if */ +#else + /* MinGW doesn't have getenv_s() */ + char *test = getenv(name); + if (*test) + return FAIL; +#endif + } return (int)_putenv_s(name, value); } /* end Wsetenv() */ diff --git a/test/testframe.c b/test/testframe.c index 5cb25ed8148..133e8ac0c6b 100644 --- a/test/testframe.c +++ b/test/testframe.c @@ -637,7 +637,8 @@ SetTest(const char *testname, int action) /* Enable a test timer that will kill long-running tests, the time is configurable * via an environment variable. * - * Only useful on POSIX systems where alarm(2) is present. + * Only useful on POSIX systems where alarm(2) is present. This does not include + * MinGW builds, which will often incorrectly decide that alarm(2) exists. */ void TestAlarmOn(void) From 839652a12283b757b9512bb3503cdfb388ede315 Mon Sep 17 00:00:00 2001 From: Dana Robinson Date: Wed, 20 Mar 2024 03:30:12 -0700 Subject: [PATCH 2/2] Fix some test lines --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 2149bb2d76a..6f9cba4f57e 100644 --- a/configure.ac +++ b/configure.ac @@ -1562,7 +1562,7 @@ AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h sys/socket.h]) ## if test "X${enable_shared}" = "Xyes"; then AC_MSG_CHECKING([if libtool needs -no-undefined flag to build shared libraries]) - case "$$host_os" in + case "$host_os" in *cygwin*|*mingw*|*aix*) ## Add in the -no-undefined flag to LDFLAGS for libtool AC_MSG_RESULT([yes]) @@ -2165,7 +2165,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ## Check whether the global variable `timezone' is defined. AC_MSG_CHECKING([for global timezone variable]) -case "$host_cpu-$host_vendor-$host_os" in +case "$host_os" in *cygwin*) AC_MSG_RESULT([disabled in CYGWIN]) ;; @@ -2196,7 +2196,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ## How do we figure out the width of a tty in characters? ## AC_CHECK_FUNCS([_getvideoconfig gettextinfo]) -case "$host_cpu-$host_vendor-$host_os" in +case "$host_os" in *cygwin*) ;; *)