On one of my projects, I decided I wanted to provide optional support
for pthreads, because I wanted portability to dinosaur compilers. Not
only did I want pthreads, but I only wanted to use them if
<stdatomic.h> was available. This took a bit of
finagling to get right, so I’ve written it up here.
Per the Autotools
Mythbuster, the correct way to indicate optional dependencies is to
check for them by default and enable them if found. If the dependency
was explicitly disabled, do not check for it; if it was requested but
not available, abort configure with an error.
First off, we need to declare an option that can be passed to
configure. AC_ARG_ENABLE
and AC_ARG_WITH
are the two autoconf macros for declaring these.
AC_ARG_ENABLE is for building optional compile-time
features, and AC_ARG_WITH is for optional external
dependencies. Because the threaded runtime build is a distinct
compile-time feature, the former is more appropriate even though it has
some system dependencies. Note that we set
enable_threaded_runtime=check for the fourth argument
(action-if-not-given), to let us distinguish whether the
unavailability of threading should be considered fatal.
# Checks for libraries.
AC_ARG_ENABLE([threaded-runtime],
[AS_HELP_STRING([--enable-threaded-runtime],
[build the threaded runtime @<:@default=check@:>@])],
[enable_threaded_runtime=$enableval],
[enable_threaded_runtime=check])The second step is to actually check for pthreads. The canonical
macro to do this is AX_PTHREAD
(GitHub
mirror). Because we want to update CC and other
environment variables only if the check succeeds, we do so inside the
first argument, overriding action-if-found. This suppresses
the default AC_DEFINE([HAVE_PTHREAD], ...) provided by the
macro, so we repeat the AC_DEFINE explicitly:
have_pthreads=no
AS_IF([test "$enable_threaded_runtime" != no],
[AX_PTHREAD([
AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
have_pthreads=yes
])])The third step is to check for <stdatomic.h>,
since this project only wanted to use threads if C11 atomics were
available. This is straightforward:
# Checks for header files.
AC_CHECK_HEADER([stdatomic.h], [have_stdatomic_h=yes], [have_stdatomic_h=no])The final step is to enable the threaded runtime if possible, and error if it was requested but impossible:
AS_IF([test "$have_pthreads" = yes && test "$have_stdatomic_h" = yes],
[enable_threaded_runtime=yes],
[AS_IF(
[test "$enable_threaded_runtime" = yes],
[AS_IF([test "$have_pthreads" = no],
[AC_MSG_ERROR([Threaded runtime requested, but pthreads was not found.])])
AS_IF([test "$have_stdatomic_h" = no],
[AC_MSG_ERROR([Threaded runtime requested, but stdatomic.h was not found.])])])
enable_threaded_runtime=no])
AC_MSG_NOTICE([Building threaded runtime: $enable_threaded_runtime])At this point you can take whatever action you need, such as setting
an AC_DEFINE or AM_CONDITIONAL.