* [musl] Detect qsort_r() support with preprocessor @ 2022-04-16 8:13 Nicholas Fraser 2022-04-16 12:01 ` Markus Wichmann 0 siblings, 1 reply; 11+ messages in thread From: Nicholas Fraser @ 2022-04-16 8:13 UTC (permalink / raw) To: musl Hello musl devs, qsort_r() has been added to musl 1.2.3 and it has been backported to the previous version of musl in Alpine. How can I detect whether this function is available using the preprocessor? The community wiki advocates "testing" for feature support, which I guess means compiling a test program like an autotools configure script. Can we not just test for a macro instead? Have you considered defining something like `__HAS_QSORT_R` to tell us directly that you support it? I am writing a cross-platform header-only library. I want my users to be able to just drop the header files of my library into their codebase. I really don't want them to have to write their own configure tests just to tell my library whether musl provides qsort_r(). I am able to detect variants of qsort_r() or qsort_s() with the preprocessor on all other platforms that support such an extension. Is there a way to detect it with musl? Nick ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-16 8:13 [musl] Detect qsort_r() support with preprocessor Nicholas Fraser @ 2022-04-16 12:01 ` Markus Wichmann 2022-04-16 14:16 ` Quentin Rameau 0 siblings, 1 reply; 11+ messages in thread From: Markus Wichmann @ 2022-04-16 12:01 UTC (permalink / raw) To: musl On Sat, Apr 16, 2022 at 04:13:56AM -0400, Nicholas Fraser wrote: > Hello musl devs, > > qsort_r() has been added to musl 1.2.3 and it has been backported to > the previous version of musl in Alpine. How can I detect whether this > function is available using the preprocessor? > > The community wiki advocates "testing" for feature support, which I > guess means compiling a test program like an autotools configure > script. Guess why that is. It is more portable to do that way than to define new non-standard macros. The only macros musl will define are standard ones. > Can we not just test for a macro instead? Have you considered > defining something like `__HAS_QSORT_R` to tell us directly that you > support it? > Unless qsort_r() were part of a new release of POSIX (then you could look at _POSIX_VERSION), or a member of an option group (then you could look at the option group macro), not really. If musl had a bespoke symbol, it would just diverge. Then musl would have its macro, glibc another one, OpenBSD would do a totally different thing again, and in the end you get a leaning tower of hostname (look it up). Plus, adding such a symbol would then basically mean it could never be retracted again. Keep going in that direction for a decade and you get a mess of non-standard symbols to keep track of. > I am writing a cross-platform header-only library. I want my users to > be able to just drop the header files of my library into their > codebase. I really don't want them to have to write their own > configure tests just to tell my library whether musl provides > qsort_r(). It's not supposed to be just for musl. Doing a configure test would correctly detect it in all configurations. Why not have a "config.h", containing all the switches? If set wrong, it just won't compile. If set right, it will compile on platforms you never even heard of. In case of pure computations like qsort_r(), there is also the possibility of the client code remedying a lacking implementation by providing the extension itself, which a version based approach will not detect correctly. > I am able to detect variants of qsort_r() or qsort_s() with > the preprocessor on all other platforms that support such an > extension. I highly doubt glibc for example provides a special symbol for qsort_r() alone, so I am guessing you are querying version numbers. Which of course fails in the face of backporting, and in case of new implementations. Whereas just writing a compile test will not. Ciao, Markus ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-16 12:01 ` Markus Wichmann @ 2022-04-16 14:16 ` Quentin Rameau 2022-04-16 17:50 ` Nicholas Fraser 0 siblings, 1 reply; 11+ messages in thread From: Quentin Rameau @ 2022-04-16 14:16 UTC (permalink / raw) To: musl Hi, > > Hello musl devs, > > > > qsort_r() has been added to musl 1.2.3 and it has been backported to > > the previous version of musl in Alpine. How can I detect whether this > > function is available using the preprocessor? > > > > The community wiki advocates "testing" for feature support, which I > > guess means compiling a test program like an autotools configure > > script. > > Guess why that is. It is more portable to do that way than to define new > non-standard macros. The only macros musl will define are standard ones. > > > Can we not just test for a macro instead? Have you considered > > defining something like `__HAS_QSORT_R` to tell us directly that you > > support it? > > > > Unless qsort_r() were part of a new release of POSIX (then you could > look at _POSIX_VERSION), or a member of an option group (then you could > look at the option group macro), not really. Just as a note, qsort_r() has indeed been added to POSIX-next, so you'd only need to ask for _POSIX_C_SOURCE with a value of 20XXXX, when it's actually been released. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-16 14:16 ` Quentin Rameau @ 2022-04-16 17:50 ` Nicholas Fraser 2022-04-16 18:42 ` Quentin Rameau 2022-04-17 2:04 ` Rich Felker 0 siblings, 2 replies; 11+ messages in thread From: Nicholas Fraser @ 2022-04-16 17:50 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 4015 bytes --] On 2022-04-16 08:01, Markus Wichmann wrote: > Unless qsort_r() were part of a new release of POSIX (then you could > look at _POSIX_VERSION), or a member of an option group (then you could > look at the option group macro), not really. If musl had a bespoke > symbol, it would just diverge. Then musl would have its macro, glibc > another one, OpenBSD would do a totally different thing again, and in > the end you get a leaning tower of hostname (look it up). All of those other platforms define symbols like __GLIBC__ and __OpenBSD__. They make it easy to detect things with the preprocessor. FreeBSD in particular publishes an exhaustive list of all possible values of __FreeBSD_version and what symbols they change or introduce: https://docs.freebsd.org/en/books/porters-handbook/versions/ It's pointless to use a configure script to detect qsort_r() on any other platform because we can detect it just fine with the preprocessor by using these symbols. Assuming you're referring to "#ifdef Considered Harmful", sorry but a 30 year old paper arguing against the use of #ifdef is not convincing. This paper predates proper function inlining optimizations. It's arguing against littering your code with #ifdefs, whereas now we know we can make zero-overhead wrapper functions to keep the portability separate from the rest of our code. > Plus, adding such a symbol would then basically mean it could never be > retracted again. Keep going in that direction for a decade and you get a > mess of non-standard symbols to keep track of. You wouldn't need a bunch of different symbols if you just defined __MUSL__. Nobody is going to remove qsort_r() from their copy of musl so as long as we know the minimum version in which it's available we'd know it's safe to use it. It doesn't have to be perfect either by the way. As long as it works in most cases we can autodetect those and let users manually configure the rest. > It's not supposed to be just for musl. Doing a configure test would > correctly detect it in all configurations. Why not have a "config.h", > containing all the switches? If set wrong, it just won't compile. If set > right, it will compile on platforms you never even heard of. I don't need a config.h for any other platform. I can autodetect things with the preprocessor everywhere except musl. Why should I add one just for musl? You're not considering the growing number of simple header-only libraries for C. Think of the stb libraries for example: https://github.com/nothings/stb These are single-file header-only libraries. Nobody wants to write a configure script for them. Nobody wants to install them into /usr/include. They want to drop the header file into their project and have it "just work". This is possible on every platform except musl. You know configure scripts aren't necessary in any other programming language right? No other language requires the use test compilation to determine the capabilities of the platform. Other programming languages have facilities to tell you what's available within the language itself. So does C, by the way, if you would only just *tell us* with the preprocessor what's available. On 2022-04-16 10:16, Quentin Rameau wrote: > Just as a note, qsort_r() has indeed been added to POSIX-next, so you'd > only need to ask for _POSIX_C_SOURCE with a value of 20XXXX, when it's > actually been released. Well that doesn't help me today. But even if it did, GCC and Clang don't define _POSIX_C_SOURCE automatically. Under glibc it's only defined under -std=gnu*, not -std=c*, and under musl (Alpine) it doesn't appear to be defined either way. Like I said, I don't control the compiler flags with which my users will compile my library. If I can reliably detect with the preprocessor whether the platform has a qsort_r() function, I can use it regardless of whether the headers actually declare it because I can just declare it myself locally in a wrapper function. This works on every platform except musl. Nick [-- Attachment #2: Type: text/html, Size: 5447 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-16 17:50 ` Nicholas Fraser @ 2022-04-16 18:42 ` Quentin Rameau 2022-04-16 23:59 ` Nicholas Fraser 2022-04-17 2:04 ` Rich Felker 1 sibling, 1 reply; 11+ messages in thread From: Quentin Rameau @ 2022-04-16 18:42 UTC (permalink / raw) To: musl Hi Nicholas, > On 2022-04-16 10:16, Quentin Rameau wrote: > > Just as a note, qsort_r() has indeed been added to POSIX-next, so you'd > > only need to ask for _POSIX_C_SOURCE with a value of 20XXXX, when it's > > actually been released. > > Well that doesn't help me today. But even if it did, GCC and Clang don't define > _POSIX_C_SOURCE automatically. Under glibc it's only defined under -std=gnu*, > not -std=c*, and under musl (Alpine) it doesn't appear to be defined either > way. Indeed, that isn't something that the compiler should define for the application, it's for the application to request it. > Like I said, I don't control the compiler flags with which my users will > compile my library. You actually do, or at least should. It's ok to have requirements about a software to work, usually dependencies, but requiring a standard (as in POSIX) environment is regular and totally legitimate. If your users decide to break your application expectations, then they must have good reasons for it and should deal with it. > If I can reliably detect with the preprocessor whether the > platform has a qsort_r() function That is the point, you cannot in the way you're going at it (until POSIX-next is released). ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-16 18:42 ` Quentin Rameau @ 2022-04-16 23:59 ` Nicholas Fraser 0 siblings, 0 replies; 11+ messages in thread From: Nicholas Fraser @ 2022-04-16 23:59 UTC (permalink / raw) To: musl On 2022-04-16 14:42, Quentin Rameau wrote: > > Like I said, I don't control the compiler flags with which my users will > > compile my library. > > You actually do, or at least should. > It's ok to have requirements about a software to work, usually > dependencies, but requiring a standard (as in POSIX) environment is > regular and totally legitimate. > > If your users decide to break your application expectations, then they > must have good reasons for it and should deal with it. But my software doesn't actually have such a requirement in reality. Why should I need to add a requirement about language standards just because you won't give us any in-language way to detect qsort_r()? My users should not need to worry about low-level things like whether they've defined _GNU_SOURCE or _POSIX_C_SOURCE just to use my code. Besides, why do you equate having a requirement with having to configure it manually? Why can't it just detect automatically with the preprocessor whether its requirements are met? Again, no manual configuration is necessary on any other platform. Note that my library doesn't even have qsort_r() as a requirement. I have a fallback but I would prefer to use what's available on the platform. This is why it's especially important for the configuration to be automatic: if the configuration is manual and they don't configure it properly it will still work but with suboptimal code. This is just as error-prone as any of your hypothetical failure cases with __MUSL__. Header-only configure-free libraries are specifically designed not to impose compiler flags or other requirements on their users. That is in fact the whole point, to not force users to build it in a special way and instead let them build it the same way as the rest of their code simply by #including it. For my libraries in particular, I go to great lengths to test that they compile cleanly under a wide variety of compiler flags on many different platforms so that users don't need to think about any of this stuff in order to use the code. > > If I can reliably detect with the preprocessor whether the > > platform has a qsort_r() function > > That is the point, you cannot in the way you're going at it (until > POSIX-next is released). You're confusing theory with practice. Of course I won't be able detect it on some theoretically perfect POSIX libc, but I don't care, because no such libc exists. I care about what works in practice. In practice, I can quite reliably detect qsort_r() with the preprocessor everywhere but musl. musl is certainly not that theoretically perfect POSIX libc by the way. For one thing, you have qsort_r(), and it's under _GNU_SOURCE. Surely you've merged it not for theoretical reasons, but because you actually want people to use it? Nick ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-16 17:50 ` Nicholas Fraser 2022-04-16 18:42 ` Quentin Rameau @ 2022-04-17 2:04 ` Rich Felker 2022-04-19 3:38 ` Nicholas Fraser 1 sibling, 1 reply; 11+ messages in thread From: Rich Felker @ 2022-04-17 2:04 UTC (permalink / raw) To: Nicholas Fraser; +Cc: musl On Sat, Apr 16, 2022 at 01:50:06PM -0400, Nicholas Fraser wrote: > On 2022-04-16 08:01, Markus Wichmann wrote: > > > Unless qsort_r() were part of a new release of POSIX (then you could > > look at _POSIX_VERSION), or a member of an option group (then you could > > look at the option group macro), not really. If musl had a bespoke > > symbol, it would just diverge. Then musl would have its macro, glibc > > another one, OpenBSD would do a totally different thing again, and in > > the end you get a leaning tower of hostname (look it up). > > All of those other platforms define symbols like __GLIBC__ and __OpenBSD__. Those do not tell you what you want to know: whether a particular interface is supported. They tell you a particular implementation name and version, which then requires you to have massive amounts of hard-coded knowledge about every platform you support, and to fail to support any platform you don't know about. This practice belongs back in the 1980s, not the 2020s. > It's pointless to use a configure script to detect qsort_r() on any other > platform because we can detect it just fine with the preprocessor by using > these symbols. No, it's not. If there were a standard or widely agreed upon macro that indicated "qsort_r is present and has the signature and semantics you expect it to have", that would make it possible to detect. But no such macro exists. I've tried to push forward an effort for defining an analog of the unistd.h macros POSIX defines, but for non-standardized but moderately to widely cross-platform extensions, but nothing has come of that so far. The existing proposal discussion is in the libc-coord list. Until that happens, *detecting* in a configure-style manner is the only way to do this. musl absolutely will not support the practice of hard-coding assumptions about the implementation. > [long rant of wrong stuff I did not read] ... Rich ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-17 2:04 ` Rich Felker @ 2022-04-19 3:38 ` Nicholas Fraser 2022-04-19 6:59 ` Markus Wichmann 2022-04-19 13:32 ` Rich Felker 0 siblings, 2 replies; 11+ messages in thread From: Nicholas Fraser @ 2022-04-19 3:38 UTC (permalink / raw) To: Rich Felker; +Cc: musl 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 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-19 3:38 ` Nicholas Fraser @ 2022-04-19 6:59 ` Markus Wichmann 2022-04-19 23:10 ` Nicholas Fraser 2022-04-19 13:32 ` Rich Felker 1 sibling, 1 reply; 11+ messages in thread From: Markus Wichmann @ 2022-04-19 6:59 UTC (permalink / raw) To: musl; +Cc: Nicholas Fraser 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 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-19 6:59 ` Markus Wichmann @ 2022-04-19 23:10 ` Nicholas Fraser 0 siblings, 0 replies; 11+ messages in thread From: Nicholas Fraser @ 2022-04-19 23:10 UTC (permalink / raw) To: musl Thanks for the replies. I'm a bit surprised to hear you agree that, given my requirements, I should ignore your features and re-implement them myself. Beyond that it looks like we won't find common ground. I'll just take the opportunity to clarify a few things: On 2022-04-19 02:59, Markus Wichmann wrote: > Since Windows/MSVC is on the list of platforms you wish to > support, that means C89. And ONLY C89. Good luck with that. You may be interested to learn that Microsoft has had full C99 support (minus those features made optional in C11) since VS 2015. This is the oldest version of the VS tools still supported. More recently, VS 2019 supports nearly all of C11 (including a conforming preprocessor.) Even before that, it was easy to make well-written C99 compile as C++ to work under Microsoft's compiler. Compiling as C++ is a virtual necessity for a header-only library anyway. > I'm pretty sure it won't work on OS-9. That would be a restriction. I think this is the main source of our disagreement. You seem very concerned that my strategy won't work on platforms I've never heard of, and that if it's not perfect, it's useless. I do provide my users the option to manually override whatever I detect in case it's wrong. I'm just trying to detect as much as I can to make it easier for them. It's okay if it only works 90% of the time, and the remaining 10% requires manual configuration. I believe it will be more like >99% though, and I had hoped musl would want to be part of that >99%. > 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. For the record I didn't ask for __MUSL_VERSION__. I asked for __HAS_QSORT_R. I asked this for exactly this reason, because I've been testing on Alpine and noticed they backported it. I only brought up __MUSL__ in comparison to what works for me on other platforms. We all agree that a standard macro like __HAS_QSORT_R would be a better solution but it will take a decade for this to get standardized. In any case, even if a version macro doesn't detect backported features, that's not a big deal. It's a temporary problem that will solve itself. This is another case of perfect being the enemy of good. > So what you would want is __MUSL_HAS_QSORT_R__, which for a growing list > of standard extensions is obviously untennable. This isn't obvious at all. I can't imagine what is so untenable about putting a simple #define next to each extension function you support. From my perspective, I think what is obvious is that you want to hide the fact that the implementation is musl, and you are opposed to macros like this simply because they could be used to reveal that you're musl. On 2022-04-19 09:32, Rich Felker wrote: > You cannot #define _GNU_SOURCE or __STDC_WANT_LIB_EXT1__ after any > standard header has already been included. Yes, I know that of course (give me a little credit here.) Maybe I was unclear. I'm not defining _GNU_SOURCE or whatever. I'm declaring the actual libc function I want to link against within the scope of my wrapper function that calls it. That's what the snippet of code I showed does. Ultimately I'm targeting the ABI, not the headers, which is why I make it work regardless of _GNU_SOURCE and such. Nick ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [musl] Detect qsort_r() support with preprocessor 2022-04-19 3:38 ` Nicholas Fraser 2022-04-19 6:59 ` Markus Wichmann @ 2022-04-19 13:32 ` Rich Felker 1 sibling, 0 replies; 11+ messages in thread From: Rich Felker @ 2022-04-19 13:32 UTC (permalink / raw) To: Nicholas Fraser; +Cc: musl 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). Rich ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2022-04-19 23:10 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-04-16 8:13 [musl] Detect qsort_r() support with preprocessor Nicholas Fraser 2022-04-16 12:01 ` Markus Wichmann 2022-04-16 14:16 ` Quentin Rameau 2022-04-16 17:50 ` Nicholas Fraser 2022-04-16 18:42 ` Quentin Rameau 2022-04-16 23:59 ` Nicholas Fraser 2022-04-17 2:04 ` Rich Felker 2022-04-19 3:38 ` Nicholas Fraser 2022-04-19 6:59 ` Markus Wichmann 2022-04-19 23:10 ` Nicholas Fraser 2022-04-19 13:32 ` Rich Felker
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/musl/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).