Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 18 Apr 2022 23:38:49 -0400
From: Nicholas Fraser <nick@...ocode.com>
To: Rich Felker <dalias@...c.org>
Cc: musl@...ts.openwall.com
Subject: Re: Detect qsort_r() support with preprocessor

On 2022-04-16 22:04, Rich Felker wrote:
 > On Sat, Apr 16, 2022 at 01:50:06PM -0400, Nicholas Fraser wrote:
 >> [long rant of wrong stuff I did not read]

It's very sad that you're not interested in hearing the problem, and that you
ignore the growing number of single-file and/or header-only libraries in C.
Here's a long list of them:

     https://github.com/nothings/single_file_libs

None of these libraries come with configure scripts. That is in fact the whole
point. They're distributed as just source code. There is no reason why plain C
source code can't be decently portable entirely on its own without any need
for configure scripts. You are just refusing to help us make it work. Yes, it's
great that you're trying to standardize macros for it, but what are we supposed
to do in the meantime? You seem more interested in adhering to standards than
in making working software.

I'm going to try to explain my use case in more detail to hopefully give you
some perspective on how this works everywhere else and why it doesn't work on
musl. If you truly don't care then feel free to ignore this email, but know
that you're ignoring a very real use case for a lot of people beyond me and my
little library.

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.

I won't say "I can detect", because then you'll say "No you can't" even though
it works fine, and we'll just go in circles telling each other we're wrong.
Instead I'll say "I am detecting".

I am detecting glibc and uClibc's qsort_r() with `#ifdef __GLIBC__`. I am
detecting Windows qsort_s() with `#ifdef WIN32`. I am detecting macOS and iOS
qsort_r() with `#ifdef __APPLE__`. I am detecting the BSDs with `#ifdef
__FreeBSD__`, `#ifdef __NetBSD__`, etc. I am detecting C11 Annex K qsort_s()
with __STDC_LIB_EXT1__ and other platform macros (e.g. __FreeBSD__.)

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:

     static inline
     void mylib_qsort_r(...) {
         extern void qsort_r(...);
         qsort_r(...);
     }

This actually works in practice. It imposes no requirements or restrictions on
how users compile my code. There is zero configuration, zero scripts to run,
zero manual steps to make it work on 99.9% of platforms in existence. I don't
need it to work on some platform I've never heard of because the odds of
someone trying to use my code on such a platform are very low, but if they ever
do, the first person who tries can just send me a patch to add support for it.
We know this same strategy will work there too because every other platform in
existence declares who they are or what features they have with macros.

This strategy works everywhere *except musl*. These are the options you've
given me to make my header-only library work on musl:

a) Add a configure script to my library. Make my users run the configure
    script, possibly execute the tests on target when cross-compiling (probably
    not necessary for qsort_r() but definitely for other features), and cache or
    install the result somewhere along with my library. (Multiply this step by
    every library they use times every platform they support.)

b) Make all users of my library either write their own configure script to
    detect musl qsort_r() and emit a config.h, or make them write this config.h
    manually, and have my library include it. (But, I can't `#include
    "config.h"` only on musl because you won't tell me you're musl, so this
    config.h becomes an added requirement on *all platforms* even though on
    every other platform it will be blank.)

c) Use my fallback, which is in fact an entire implementation of `qsort_r()`,
    intended only for platforms that don't have one. This is of course the most
    attractive option because it's the only one that doesn't add a configuration
    burden on my users. Remind me, why did you bother implementing qsort_r()
    again? Because the best option you've left me with is the one where I ignore
    it.

Is this really what you want the future of C programming to be like? You want
every little piece of source code to have a configure script attached to it to
probe the platform, or have a bunch of manual configuration steps just to
figure out what the platform already knows but won't tell us? Are all of musl's
features secrets we have to tease out with these out-of-language hacks?

Nick

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.