Skip to content

Instantly share code, notes, and snippets.

@jperkin
Last active July 19, 2021 10:41
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jperkin/b08f9108daf8d0ac695067d71f882a9d to your computer and use it in GitHub Desktop.
Save jperkin/b08f9108daf8d0ac695067d71f882a9d to your computer and use it in GitHub Desktop.
SunOS, _XOPEN_SOURCE, _POSIX_C_SOURCE, C99, etc...

How To Correctly Set _XOPEN_SOURCE and __EXTENSIONS__

This is a work-in-progress, but aims to help navigate the murky waters of setting _XOPEN_SOURCE in such a way that it is compatible across C standards on SunOS systems.

Introduction

A table is worth a thousand words. Defines used in a default compilation environment (i.e. no -std=.. specified):

Define GCC 4.x (C90) or older GCC 5.x (C99) or newer
_XOPEN_SOURCE=500 Ok Error
_XOPEN_SOURCE=600 Error Ok
_POSIX_SOURCE Ok Error
_POSIX_C_SOURCE=199506L Ok Error
_POSIX_C_SOURCE=200112L Error Ok
__EXTENSIONS__ Ok Ok

The basic problem boils down to this:

  • You cannot use _XOPEN_SOURCE=500 or older if building with a C99 or newer compiler.
  • You cannot use _XOPEN_SOURCE=600 or newer if building with a C90 or older compiler.

The problem is exacerbated by different compiler defaults, meaning that the same piece of code may break depending on which version of GCC you are using:

  • GCC <= 4.x default to C90 or older.
  • GCC >= 5.x default to C99 or newer.

Thus:

  • Code which unconditionally defines _XOPEN_SOURCE=500 or older will fail with GCC >= 5.x
  • Code which unconditionally defines _XOPEN_SOURCE=600 or newer will fail with GCC <= 4.x

An alternative selection of standards is done by _POSIX_C_SOURCE, and this generally falls into the same issues:

  • _POSIX_C_SOURCE=199506L (if set) or older must be used for C90 or older
  • _POSIX_C_SOURCE=200112L (if set) or newer must be used for C99 or newer

How To Fix

_XOPEN_SOURCE=500

The normal way we can resolve this is by testing for __STDC_VERSION__ and handle accordingly.

#if __STDC_VERSION__ - 0 < 199901L
#define _XOPEN_SOURCE 500
#else
#define _XOPEN_SOURCE 600
#endif

This however may not be appropriate in all situations. Some OS may behave differently if _XOPEN_SOURCE is set compared to the OS defaults, so care must be taken.

Generally the rule will be that if _XOPEN_SOURCE is already being set, then the above should be safe. However if it is being added, then it's probably worth wrapping it inside a __sun section:

#if defined(__sun)
#  if __STDC_VERSION__ - 0 < 199901L
#define _XOPEN_SOURCE 500
#  else
#define _XOPEN_SOURCE 600
#  endif
#endif

_XOPEN_SOURCE=600

If the software has hardcoded _XOPEN_SOURCE=600 then the simplest fix, at least in a pkgsrc environment, is to ensure the software is built in a C99 environment by setting USE_LANGUAGES:

USE_LANGUAGES+= c99

Care should be taken if this is set in a public header, as then every dependency will also need C99.

If the software requires adding _XOPEN_SOURCE=600 and does not already set _XOPEN_SOURCE in the source, then

USE_LANGUAGES+= c99
CPPFLAGS.SunOS+=  -D_XOPEN_SOURCE=600

will avoid the need for patching.

__EXTENSIONS__

Adding __EXTENSIONS__ to expose additional features should be safe in any C environment.

_XOPEN_SOURCE_EXTENDED

Setting _XOPEN_SOURCE_EXTENDED effectively ignores what _XOPEN_SOURCE is set to and forces XPG4v2 mode.

This is wrong. Don't ever set it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment