[Issue 24725] New: core.sys.linux: feature detect glibc functions at build time

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Aug 27 19:37:53 UTC 2024


https://issues.dlang.org/show_bug.cgi?id=24725

          Issue ID: 24725
           Summary: core.sys.linux: feature detect glibc functions at
                    build time
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: druntime
          Assignee: nobody at puremagic.com
          Reporter: a.horodniceanu at proton.me

This has come up as an issue in https://github.com/dlang/phobos/pull/9048 but
the short version is: druntime bindings should match up what the C system
headers expose, as much as possible.

The advantages is simple, it lowers the amount of manual inspection a user has
to do to check for declarations inside libc or if those declarations will exist
on somebody else's computer when compiling the same code. There are no
disadvantages to doing this outside of needing to implement the change.

The two main ways of implementing this are:
1. Embedding some form of information when druntime is built.

This, again, can be done in two ways, either embed to full version of glibc or
embed only if a function is available. The former would require to inspect the
headers of glibc at build time and extract the `__GLIBC__` and
`__GLIBC_MINOR__` macros. The meson build system has support for this:
https://mesonbuild.com/Reference-manual_returned_compiler.html#compilerget_define,
but neither autotools, used by gdc, nor cmake, used by ldc, support this. The
other approach is performing checks for individual function which both build
systems would known how to perform. dmd has been left out because it only uses
a makefile so code has to be written manually to support this.

Embedding the version would be the best approach as the check would have to be
carried only once during the build and the `config.d` file would have `enum
__GLIBC__ = ...` and `enum __GLIBC_MINOR__ = ...` set inside it. For
convenience, `config.d` would also provide a function `__GLIBC_PREREQ` witch
does the same thing as the glibc provided macro, which is checking that the
glibc version is high enough. To provide a function that has been recently
added a modules inside `core.sys.linux` can do:
```
import core.sys.linux.config;
static if (__GLIBC_PREREQ(2, 34))
void closefrom(int);
```

This would provide the `closefrom` declaration on systems that have a glibc
version of at least 2.34. This is expressive as it clearly documents on which
systems the function exists. It also makes adding functions easier as the
version of glibc has already been determined. The downside is that the build
systems used by gdc and ldc don't support this out of the box.

The other approach involves adding an enum for each function to `config.d`
like:
```
module core.sys.linux.config;
enum HAVE_CLOSEFROM = true;
```

```
module core.sys.linux.unistd;
import core.sys.linux.config;
static if (HAVE_CLOSEFROM)
void closefrom(int);
```

The value of `HAVE_CLOSEFROM` would be generated during the build and saved
inside `config.d`. In this case it is not abundantly clear how "portable" the
closefrom function is, or on which systems it is available. This approach also
makes it harder to subsequently add other functions as each addition would
require an additional `enum` value and a check inside the build system.

Both of these approaches would lead to the same interface being exposed so the
differences are only in readability/ease of implementation.

Both of these solutions would be most effective when building druntime on
recent systems. If druntime is build on an older system, with the purpose of
creating portable binaries like the dmd release archives, the changes wouldn't
be as big as the detected glibc version would be older than what may be
available on a user's system. When built on newer systems, however, these
changes would be more substantial as they allow druntime to provide more
definitions.

A back-and-fourth topic in the PR that started this has been whether this
affects the portability of the code that uses druntime or phobos. The answer is
no, for portability sake's the most relevant thing is the version of glibc you
build the code against. As an example, if druntime and phobos are built against
glibc-2.20 then any D application that uses those would be able to run on a
system with glibc-2.20 or newer. The version of glibc the two libraries are
built against refers to the version that those libraries are linked against. It
has little bearing on portability which or how many functions from glibc the
code uses, the minimum glibc version requirement is given during the linking
step.

2. Automatically parsing C headers
This could be provided through importC and expose to the D code the same
functions as would be provided to C. This would be great if it worked, however:
- there are still a lot of edge cases that importC doesn't support:
https://github.com/dlang/dmd/blob/4a5c56d0f7f3f84ec7f6bf1f980834f72e211824/compiler/test/compilable/stdcheaders.c
- gdc doesn't support #include's with importC.

The current code, while not optimal, has the advantage that it doesn't break.
For this reason I consider that either of the solutions described in 1. are
worth pursueing.

--


More information about the Digitalmars-d-bugs mailing list