Adding Optional Support for pthreads

Posted on July 29, 2026 by Jack Kelly
Tags: , ,

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.

Previous Post
All Posts | RSS | Atom
Next Post
Copyright © 2026 Jack Kelly
Site generated by Hakyll (source)