back

by uecker·5d ago·view on hn ↗
The mechanism actually does not solve the problem it claims to solve.
1 comments
How so?
Because it imagines that no library other than libc has an ABI that depends on intmax_t.

Suppose I have a libfoo that has a public function that takes an intmax_t parameter. Or that has a public struct with an intmax_t field. It will be compiled for a particular definition of intmax_t. If you try to link it with a program that uses a different definition, it will fail.

The article's solution with the "MY_LIBC_NEW_CODE" define cannot work because no existing C code knows about "MY_LIBC_NEW_CODE".

The proposed mechanism is somewhat useful to a library that wants to provide multiple incompatible implementations of a function. (But this is mostly only interesting for libc implementations that need to handle historic incompatibilities between all the various Unix specs. Other libraries can just give their new, incompatible function a new name.) It's useless if you want to make an incompatible change to a type definition.

> Because it imagines that no library other than libc has an ABI that depends on intmax_t.

I don't get quite the same impression. The sense I get is more that such a change would basically need to happen "bottom-up":

> Some of [the scenarios that aren't fixed by this proposal] are just the normal dependency management issues. If you build a library on top of something else that uses one of the changed types (such as intmax_t or something else), then you can’t really upgrade until your dependents do.

> <snip>

> For those of us in large ecosystems who have to write plugins or play nice with other applications and system libraries, we’re generally the last to get the benefits.

In which case the benefit of the proposal (as far as I understand) is that such bottom-up changes can occur without forcibly breaking other consumers.

It was never really possible to compile a library with one C compiler and expect it to link against code produced by another C compiler, unless both compilers happen to agree on specific ABI details that are either defined outside the C standard or not at all.

And to be honest, this sort of compiler-specific ABI interoperability is a non-problem that doesn't need solving, it's at most relevant for software developers of closed source libraries who distribute the libraries as precompiled blobs. But those must be stamped out for different target-triples anyway.

I'm... a bit confused? I wasn't thinking about inter-compiler interop at all.
Compiler interoperability is the only ABI related problem area that's remotely in the scope for the C standard, but IMHO not even that (it's really not a problem that needs solving).

Ultimately any ABI discussions need to happen between CPU and OS vendors, compiler toolchains implement whatever comes out of those discussions.

> Compiler interoperability is the only ABI related problem area that's remotely in the scope for the C standard

idk, given how ABI impacts the evolution of C I think it's not unreasonable to provide a mechanism by which ABI can be evolved even if it's not specifically for compiler interop.

> Ultimately any ABI discussions need to happen between CPU and OS vendors, compiler toolchains implement whatever comes out of those discussions.

I think part of the article author's reasoning for proposing this feature is that toolchains have implemented something like this feature to try to address ABI issues and that the rest of the ecosystem could benefit from a similar technique.

Huh, compiler interoperability is extremely useful. It usually works by ABI groups defining a common ABI for each architecture and compilers then following these ABIs (although not required a compilers that does not is poor)
> inter-compiler interop

Inter-compiler interop is also in play when the two compilers are the same one at different versions, or even potentially flags.

The issue is that a programmer is allowed to declare a function on its own without including the header, but then a function aliasing feature would not be visible and does not help. But if we waived this allowance, then a simple macro would do the job as well.
I think the most recent revision of the proposal basically says it not helping for such use cases is intentional? e.g., from Section 4.4.1. Standard Library Redeclaration [0]:

> Thankfully, we are not particularly concerned about the ability to upgrade this [user-redeclared stdlib] function: users who are declaring Standard Library functions without including the header like this are doing this strictly as experts. They have a strong expectation of what symbol they are getting from their distribution. Transparent aliases are meant to be used for functions which rely on type definitions or structures which may change, prompting the need to provide updated global variables and updated functions without breaking old binaries.

> <snip>

> Therefore, we do not do anything to support or inhibit such declarations. Implementations looking to keep such declarations working from older versions of code should consider leaving those old symbols within their binary artifacts (system tables, shared/static libraries, etc.) to continue supporting such a use case; this proposal is not going to address it or the myriad of other issues around this (such as strong/weak symbols and other attributes/aliasing issues).

To be fair, that section is talking about the stdlib specifically, but nothing jumps out to me as precluding it applying to libraries in general.

[0]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3913.htm#d...

Indeed, it now admits this. But what problem is this then really solving?
> But what problem is this then really solving?

Well, I'd presume that's what the paper's "Introduction & Motivation" section is for. Do you take issue with the authors' statements there?

Yes, it does not solve the problems described there.
For lack of the creativity needed for better wording (and hoping I'm not inadvertently going in circles here) - how so?