Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Tue, 19 Apr 2022 09:32:12 -0400
From: Rich Felker <>
To: Nicholas Fraser <>
Subject: Re: Detect qsort_r() support with preprocessor

On Mon, Apr 18, 2022 at 11:38:49PM -0400, Nicholas Fraser wrote:
> Just to recap: I'm writing a header-only library. My intention is for users to
> just put the headers on their include path and use it, no configuration needed.
> I'd like to use any variation of qsort_r()/qsort_s() that's available on the
> platform.
> GNU/musl/POSIX-next qsort_r() and C11 Annex K qsort_s() are virtually the
> same; Free/Net/DragonFlyBSD and Apple qsort_r() are the same; and Windows
> qsort_s() is the outlier. There are only three possible prototypes so it's
> trivial for my code to permute the arguments to match what's available. All I
> need to do is detect which one the platform has.

This would be a great usage case for the "Macro-based advertisement of
libc extensions" proposal on libc-coord. The right thing to do here is
to try to move that forward, explaining how it solves your problem.
I'll try to revitalize that.

> In cases where the headers declare it conditionally, I simply declare it myself
> so that my users don't need to define _GNU_SOURCE or __STDC_WANT_LIB_EXT1__ or
> whatever:

You cannot #define _GNU_SOURCE or __STDC_WANT_LIB_EXT1__ after any
standard header has already been included. The only place they can
safely be defined is at the top of the source file before any headers,
or on the command line with -D. There are two reasons for this: one is
that the rules say so (both POSIX and glibc document this, in addition
to musl). The other more mechanical reason is that the header you're
trying to get the definitions from might already have been included
(directly or indirectly) earlier, whereby the multiple-inclusion guard
prevents it from exposing anything else the second time it's included.
This extends to the case where the FTMs are actually processed by a
unified file (like features.h) into internal-use-only macros on the
first inclusion of any standard heaader. For this reason, it's
possible that even headers which weren't already included once will
still fail to see the updated FTMs.

So, defining these from a header-only library is an on-starter unless
you impose a requirement on the caller that they must include your
header absolute-first (and then they can only use one such header-only
library). An approach that actually works is just documenting that the
caller must ensure they're defined appropriately for features they
want your library to be able to use. Or, just being compatible with
whatever choice the caller made (so using your own fallback or
whatever if it's not exposed).


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.