William Breathitt Gray
William Breathitt Gray

Reputation: 11986

How to check for POSIX-conformance with autoconf

My project follows the POSIX.1-2008 standard and I would like to ensure that the user's implementation conforms to this standard.

So far I've been using AC_DEFINE to define the _POSIX_C_SOURCE macro as specified in the POSIX standard.

AC_DEFINE([_POSIX_C_SOURCE], [200809L], [Define the POSIX version])

However, since this is a simple C preprocessor #define macro , it does nothing to prevent an implementation that isn't POSIX-compliant from compiling.

Does Autoconf offer a standard macro to check for the implementation's conformance to a specific POSIX standard?

Upvotes: 1

Views: 1631

Answers (2)

William Breathitt Gray
William Breathitt Gray

Reputation: 11986

To portably check if the user's implementation conforms to a specific POSIX standard, use AC_EGREP_CPP to check the existence and value of _POSIX_VERSION:

AC_EGREP_CPP(posix_200809L_supported,
             [#define _POSIX_C_SOURCE 200809L
              #include <unistd.h>
              #ifdef _POSIX_VERSION
              #if _POSIX_VERSION == 200809L
              posix_200809L_supported
              #endif
              #endif
             ],
             [],
             [AC_MSG_FAILURE([*** Implementation must conform to the POSIX.1-2008 standard.])]
)

This works due to several guarantees made by POSIX.


Step 1

We first set _POSIX_C_SOURCE to 200809L.

#define _POSIX_C_SOURCE 200809L

POSIX.1-2008 states that when an application includes a header described by POSIX.1-2008, and when this feature test macro (_POSIX_C_SOURCE) is defined to have the value 200809L, then all symbols required by POSIX.1-2008 to appear when the header is included shall be made visible.


Step 2

So when we include unistd.h in the next line, all symbols required by POSIX.1-2008 to appear in unistd.h will be made visible.

#include <unistd.h>

Since _POSIX_VERSION is required to appear in unistd.h, it too is now visible.


Step 3

_POSIX_VERSION is required by the POSIX.1-2008 standard to be set to a value of 200809L.

For implementations conforming to POSIX.1-2008, the value shall be 200809L.

So all we have to do now is test if _POSIX_VERSION is defined, and if so, whether it's set to a value equal to 200809L.

#ifdef _POSIX_VERSION
#if _POSIX_VERSION == 200809L

Checking whether _POSIX_VERSION is defined helps us determine if there is support for any POSIX standard on the implementation. Checking the value of _POSIX_VERSION helps us narrow down whether a specific version of the POSIX standard is supported.

If both of these conditions are true, then the implementation almost certainly supports POSIX.1-2008.

Upvotes: 3

Brett Hale
Brett Hale

Reputation: 22348

Here's an autoconf test that relies on the negative array size trick:

  AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
    [[#include <unistd.h>]],
    [[int n[(_POSIX_VERSION == 200809L) ? (-1) : (+1)];]])],
    AC_MSG_FAILURE([POSIX.1-2008 profile required]))

Using getconf is fine if the software is only being built on the host machine.

ac_posix_version=`getconf _POSIX_VERSION`
if test $ac_posix_version -ne 200809 >/dev/null 2>&1
  AC_MSG_FAILURE([POSIX.1-2008 profile required])
fi

This might have bugs (not tested). It's clearly of no use in cross compilation.

Upvotes: 2

Related Questions