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 08:59:54 +0200
From: Markus Wichmann <nullplan@....net>
To: musl@...ts.openwall.com
Cc: Nicholas Fraser <nick@...ocode.com>
Subject: Re: Detect qsort_r() support with preprocessor

This will likely be pointless, but I'll try once more.

On Mon, Apr 18, 2022 at 11:38:49PM -0400, Nicholas Fraser wrote:
> 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
>

No, YOU are not interested in hearing the reasons for why what you want
is bad and leads to technical debt. There is no reason why single
file libraries should not have a config section at the top or something.
The only alternative left to you is to use standards that are definitely
supported. Since Windows/MSVC is on the list of platforms you wish to
support, that means C89. And ONLY C89. Good luck with that.

> 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.
>

That last one has been floated before and just does not fly. You have
been pointed in the direction of something to make it work reliably
everywhere and refuse to use that solution because apparently you think
running a script or writing a 0 or 1 into a single line of configuration
is undue burden on programmers who already cannot be arsed to do their
job. But making Rich maintain a growing list of macros somehow is not.

See, this is what I don't get: Your target audience is programmers, not
end users. Can they not be expected to fill in a configuration once?
They will already have to expend some effort integrating your library
into their programs, anyway, so it hardly changes things.

Indeed there is no reason for plain C being unportable. But the only way
to really make it portable is to refuse to use any feature beyond the
lowest common denominator, which is usually going to be C89. So, no
qsort_r() for you.

The alternative is to maintain a growing list of assumptions about
implementations, each of which may turn around next release without
warning. Or, you know, your source code can grow out of date.

> 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.

Then maybe that's a bad intention. The only way to do that with the list
of platforms you added later is to not go beyond C89.

>
> 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".
>

And here the boy who cried "you're not listening" goes on to not listen
himself.

> 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__.)
>

And you listed all of that stuff with a straight face. didn't you? The
only standard macro in all of these is __STDC_LIB_EXT1__, an admittedly
rarely used one. What about newlib? newlib is the C implementation
underlying much of Cygwin, which last I checked was still pretty
popular. At least I use it regularly. And you can get it to define
WIN32, but it doesn't have qsort_s(). But it has both versions of
qsort_r().

Anyway, what do you want? Imagine if there was a __MUSL__ macro, and had
been there last version already. That would mean that the presence of
__MUSL__ tells you nothing about whether qsort_r() is supported. So you
would need __MUSL_VERSION__ or something.  But then Alpine went ahead
and backported it to earlier versions. So there are versions of musl
1.2.2 out there with qsort_r() and those without it. So again, the macro
you are begging for would not tell you what you want to know.

So what you would want is __MUSL_HAS_QSORT_R__, which for a growing list
of standard extensions is obviously untennable. If instead you just
tested the environment once, you could do it dynamically for all
possible C implementations.

Or you wait for the next version of POSIX to come out and test the POSIX
version macros. That means there will be C libraries with the function
you want but not declaring support for them, but then, such is life.

> 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.

I'm pretty sure it won't work on OS-9. That would be a restriction.

> 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.
>

No, they don't declare who they are. They declare who they are
emulating. clang defines __GNUC__, uclibc defines __GLIBC__, and why?
Because people like you cannot be bothered to run configure tests for
the features you want.

> 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

Well, you took the long way around, but arrived at the correct
conclusion. Especially in the case of qsort_r(), the only thing that
reliably works on all platforms is to implement it yourself in the
absence of standard macros. Since you are already doing that, just
always using that implementation is less code than whatever harnesses
around qsort_r() and qsort_s() you have built. And less code is usually
less bad.

>. 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.
>

The best option for you and your highly specific and, frankly,
counterintuitive requirements, that have programmers integrate a library
but not able to write a config header.

> 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?
>

What do you mean "future"? At this time you already only have two
sort-of reliable ways to detect standard extensions: Either test for
them, and due to the fluid nature of many libraries, that means test for
the actual interface, not implementation name and version, or else wait
for it to be standardized and test for standard macros. The former finds
all implementations but requires compile-time configuration, the always
works but fails to find some implementations. You have to die some way,
so choose.

Ciao,
Markus

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.