Skip to content

Commit

Permalink
Fixes several MinGW + Autotools issues (#4190)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
derobins authored Mar 20, 2024
1 parent 4c0f146 commit 56c527d
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 103 deletions.
4 changes: 2 additions & 2 deletions config/cmake/H5pubconf.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -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 <zlib.h> header file. */
Expand Down
227 changes: 128 additions & 99 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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"
;;
Expand All @@ -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 <features.h> defines
## __USE_POSIX, which is required to get the prototype for fdopen
Expand Down Expand Up @@ -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])
Expand Down Expand Up @@ -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 <stdlib.h>
#include <pthread.h>
],[
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])
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
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
;;
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 <stdlib.h>
#include <pthread.h>
],[
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
Expand All @@ -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_os" in
*cygwin*)
AC_MSG_RESULT([disabled in CYGWIN])
;;
*)
Expand Down Expand Up @@ -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_os" in
*cygwin*)
;;
*)
AC_CHECK_FUNCS([GetConsoleScreenBufferInfo])
Expand Down Expand Up @@ -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
##
Expand Down Expand Up @@ -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])
;;
*)
Expand Down
8 changes: 8 additions & 0 deletions src/H5private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <windows.h>

#include <direct.h> /* For _getcwd() */
Expand Down
9 changes: 8 additions & 1 deletion src/H5system.c
Original file line number Diff line number Diff line change
Expand Up @@ -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() */
Expand Down
3 changes: 2 additions & 1 deletion test/testframe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 56c527d

Please sign in to comment.