Jump to page: 1 2
Thread overview
[D-runtime] Supporting different C libraries and architectures
Feb 25, 2012
Johannes Pfau
Feb 25, 2012
Sean Kelly
Feb 26, 2012
Johannes Pfau
Feb 26, 2012
Jonathan M Davis
Feb 26, 2012
Johannes Pfau
Feb 26, 2012
David Nadlinger
Feb 26, 2012
Jonathan M Davis
Feb 26, 2012
mta`chrono
Feb 26, 2012
David Nadlinger
Feb 26, 2012
Sean Kelly
Feb 26, 2012
Iain Buclaw
Feb 27, 2012
Johannes Pfau
Feb 27, 2012
Iain Buclaw
Feb 27, 2012
Johannes Pfau
Feb 26, 2012
Brad Roberts
Feb 26, 2012
Martin Nowak
February 25, 2012
This is probably less a problem for DMDs druntime, but we hit this issue with gdc and the android port now, so I thought I'll also post this message here, maybe someone has a good idea.

Android uses a custom C library (Bionic) which is not 100% Posix compatible. With the current approach of supporting different systems using version() blocks, this will lead to lots of changes in all the core/* files. And it will get much worse once we try to support other C libraries (newlib for DS/Wii homebrew, uclibc/dietlibc/eglibc for embedded linux, etc). The current aproach is already broken for Android, as druntime assumes version(linux) --> glibc which is not true. One such broken example is the usage of the glibc "backtrace" function.

Here's the original message sent to the D.gnu newsgroup:

------------------------------------------------------------------------
As recently discussed in a pull request it would be great if we could make it easier to port druntime to different architectures. Special casing every C library, every architecture and every OS using version blocks could lead to difficult to maintain code, so we need a better solution.

As far as I can see, the biggest differences are caused by different C libraries, not by different architectures (except 32bit vs 64 bit differences). For example glibc headers seem to be very similar for arm and x86, but bionic vs. glibc brings more differences. Bionic initially didn't support anything wchar_t related, so core.stdc.wchar_ and core.stdc.wctype couldn't work with android at all. And C libraries vary even more in the subset of posix functionality they support.

We need a directory scheme to support
* Different C libraries
   * on different OS (glibc/bsd glibc/linux)
   * on the same OS (glibc on linux, bionic on linux, uclibc on
     linux, ...)
* Different architectures (ARM, X86, MIPS, PPC, SH4, ...)

I propose the following directory layout, but of course better solutions are appreciated:

druntime
|-core
|---stdc
|---sync
|---sys
|-----posix
|-gc
|-gcstub
|-rt
|-gcc
|---arch
|-----glibc
|-------core
|---------stdc
|---------sync
|---------sys
|-----------posix
|-----bionic
|-------stdc
|-------sync
|-------core
|---------sys
|-----------posix
|-----newlib
|-------stdc
|-------sync
|-------core
|---------sys
|-----------posix

Code in the gc, gcstub and rt directories shouldn't depend on special C libraries, small differences can be solved using version() blocks.

Every C library get's it's  own bindings in the gcc.arch package. I'm not sure if those bindings should only provide functionality included in core, or whether these bindings should include additional, C library specific bindings.

The files in core.* would reference the corresponding files in gcc.arch.core.*

The downside of that approach is that we'll have some code duplication, especially for similar C libraries. And merging changes is therefore not that easy as well. However, as the C and Posix headers don't change often, that's probably neglectable.

Here are some examples for that directory scheme:

core/stdc/config.d (Should be shared with dmd druntime?)
-----------------------------------------------
enum LibC
{
     GlibC,
     uClibc,
     dietlibc,
     newlib,
     dmc, //digitalmars, windows
     msvcrt,
     ...,
     unknown
}

//Need some way to define this correctly
enum libC = LibC.GlibC;
enum string libCVersion = ""; //Free form version number
-----------------------------------------------

core/stdc/math.d
-----------------------------------------------
import core.stdc.config;

static if(libC == LibC.GlibC)
{
     public import gcc.arch.glibc.core.stdc.math;
}
else
{
     static assert(false, "C library '" ~ libC ~ "' not supported in " ~
     __FILE__);
}

//Maybe put generic parts here?
-----------------------------------------------

core/sys/posix/dirent.d
-----------------------------------------------
import core.stdc.config;

static if(libC == LibC.GlibC)
{
     /*
      * I admit this looks horrible. We can probably remove the core
      * part, maybe even gcc, so arch.glibc.sys.posix.dirent?
      * or glibc[.core].sys.posix.dirent?
      */
     public import gcc.arch.glibc.core.sys.posix.dirent;
}
else static if(libC == LibC.GlibC)
{
     public import gcc.arch.glibc.core.sys.posix.dirent;
}
else
{
     static assert(false, "C library '" ~ libC ~ "' not supported in " ~
     __FILE__);
}
-----------------------------------------------

Maybe we could use pragma(msg) warnings instead of static asserts, so
it'd be possible to import the modules in any case and use
traits(__compiles) to check for specific symbols/functions.

-- 
Johannes Pfau



February 25, 2012
Ugh. It's worth noting that the current definitions for OSX, Linux, and FreeBSD are all glibc and all relatively different, too.

On Feb 25, 2012, at 9:31 AM, Johannes Pfau <johannespfau@googlemail.com> wrote:

> This is probably less a problem for DMDs druntime, but we hit this issue with gdc and the android port now, so I thought I'll also post this message here, maybe someone has a good idea.
> 
> Android uses a custom C library (Bionic) which is not 100% Posix compatible. With the current approach of supporting different systems using version() blocks, this will lead to lots of changes in all the core/* files. And it will get much worse once we try to support other C libraries (newlib for DS/Wii homebrew, uclibc/dietlibc/eglibc for embedded linux, etc). The current aproach is already broken for Android, as druntime assumes version(linux) --> glibc which is not true. One such broken example is the usage of the glibc "backtrace" function.
> 
> Here's the original message sent to the D.gnu newsgroup:
> 
> As recently discussed in a pull request it would be great if we could make it easier to port druntime to different architectures. Special casing every C library, every architecture and every OS using version blocks could lead to difficult to maintain code, so we need a better solution.
> 
> As far as I can see, the biggest differences are caused by different C
> libraries, not by different architectures (except 32bit vs 64 bit
> differences). For example glibc headers seem to be very similar for arm
> and x86, but bionic vs. glibc brings more differences. Bionic     initially
> didn't support anything wchar_t related, so core.stdc.wchar_ and
> core.stdc.wctype couldn't work with android at all. And C libraries
> vary even more in the subset of posix functionality they support.
> 
> We need a directory scheme to support
> * Different C libraries
>   * on different OS (glibc/bsd glibc/linux)
>   * on the same OS (glibc on linux, bionic on linux, uclibc on
>     linux, ...)
> * Different architectures (ARM, X86, MIPS, PPC, SH4, ...)
> 
> I propose the following directory layout, but of course better solutions are appreciated:
> 
> druntime
> |-core
> |---stdc
> |---sync
> |---sys
> |-----posix
> |-gc
> |-gcstub
> |-rt
> |-gcc
> |---arch
> |-----glibc
> |-------core
> |---------stdc
> |---------sync
> |---------sys
> |-----------posix
> |-----bionic
> |-------stdc
> |-------sync
> |-------core
> |---------sys
> |-----------posix
> |-----newlib
> |-------stdc
> |-------sync
> |-------core
> |---------sys
> |-----------posix
> 
> Code in the gc, gcstub and rt directories shouldn't depend on special C libraries, small differences can be solved using version() blocks.
> 
> Every C library get's it's  own bindings in the gcc.arch package. I'm not sure if those bindings should only provide functionality included in core, or whether these bindings should include additional, C library specific bindings.
> 
> The files in core.* would reference the corresponding files in gcc.arch.core.*
> 
> The downside of that approach is that we'll have some code duplication, especially for similar C libraries. And merging changes is therefore not that easy as well. However, as the C and Posix headers don't change often, that's probably neglectable.
> 
> Here are some examples for that directory scheme:
> 
> core/stdc/config.d (Should be shared with dmd druntime?)
> -----------------------------------------------
> enum LibC
> {
>     GlibC,
>     uClibc,
>     dietlibc,
>     newlib,
>     dmc, //digitalmars, windows
>     msvcrt,
>     ...,
>     unknown
> }
> 
> //Need some way to define this correctly
> enum libC = LibC.GlibC;
> enum string libCVersion = ""; //Free form version number
> -----------------------------------------------
> 
> core/stdc/math.d
> -----------------------------------------------
> import core.stdc.config;
> 
> static if(libC == LibC.GlibC)
> {
>     public import gcc.arch.glibc.core.stdc.math;
> }
> else
> {
>     static assert(false, "C library '" ~ libC ~ "' not supported in     " ~
>     __FILE__);
> }
> 
> //Maybe put generic parts here?
> -----------------------------------------------
> 
> core/sys/posix/dirent.d
> -----------------------------------------------
> import core.stdc.config;
> 
> static if(libC == LibC.GlibC)
> {
>     /*
>      * I admit this looks horrible. We can probably remove the core
>      * part, maybe even gcc, so arch.glibc.sys.posix.dirent?
>      * or glibc[.core].sys.posix.dirent?
>      */
>     public import gcc.arch.glibc.core.sys.posix.dirent;
> }
> else static if(libC == LibC.GlibC)
> {
>     public import gcc.arch.glibc.core.sys.posix.dirent;
> }
> else
> {
>     static assert(false, "C library '" ~ libC ~ "' not supported in     " ~
>     __FILE__);
> }
> -----------------------------------------------
> 
> Maybe we could use pragma(msg) warnings instead of static asserts, so
> it'd be possible to import the modules in any case and use
> traits(__compiles) to check for specific symbols/functions.
> -- 
> Johannes Pfau
> _______________________________________________
> D-runtime mailing list
> D-runtime@puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

February 26, 2012
Am 25.02.2012 20:52, schrieb Sean Kelly:
> Ugh. It's worth noting that the current definitions for OSX, Linux, and FreeBSD are all glibc and all relatively different, too.
FreeBSD doesn't use glibc by default although glibc has FreeBSD support. They use "BSD libc" http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/

The OSX C library seems to be part of libSystem. And that seems to use " Darwin libc" http://www.opensource.apple.com/source/Libc/ which is BSD licensed and therefore can't be based on glibc.

-- 
Johannes Pfau



February 26, 2012
On Sunday, February 26, 2012 10:02:00 Johannes Pfau wrote:
> Am 25.02.2012 20:52, schrieb Sean Kelly:
> > Ugh. It's worth noting that the current definitions for OSX, Linux, and FreeBSD are all glibc and all relatively different, too.
> FreeBSD doesn't use glibc by default although glibc has FreeBSD support. They use "BSD libc" http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/
> 
> The OSX C library seems to be part of libSystem. And that seems to use " Darwin libc" http://www.opensource.apple.com/source/Libc/ which is BSD licensed and therefore can't be based on glibc.

If it's varying for pretty much every OS, and the problem is that android doesn't match what linux does but is considered linux, then maybe there should be an android version and then either android isn't linux, or it's both linux and android, and we just do like we do with Posix and put the more specific one first in the version lists.

- Jonathan M Davis
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

February 26, 2012
Am 26.02.2012 10:45, schrieb Jonathan M Davis:
> On Sunday, February 26, 2012 10:02:00 Johannes Pfau wrote:
>> Am 25.02.2012 20:52, schrieb Sean Kelly:
>>> Ugh. It's worth noting that the current definitions for OSX, Linux, and
>>> FreeBSD are all glibc and all relatively different, too.
>> FreeBSD doesn't use glibc by default although glibc has FreeBSD support.
>> They use "BSD libc" http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/
>>
>> The OSX C library seems to be part of libSystem. And that seems to use "
>> Darwin libc" http://www.opensource.apple.com/source/Libc/ which is BSD
>> licensed and therefore can't be based on glibc.
> If it's varying for pretty much every OS,
I still think the big differences are between different C libraries, not OS (and different OS often use different C libraries, but there's also a glibc port for FreeBSD, so there are exceptions).
> and the problem is that android
> doesn't match what linux does but is considered linux,
'Linux' is just the kernel, and Linux can use many different C libraries(eglibc, uclibc, glibc, dietlibc, bionic, musl). The problem is that druntime assumes that linux == glibc which isn't true. glibc specific code should be guarded with a version(Glibc)/static if(libC == Glibc) and not version(linux).
>   then maybe there should
> be an android version and then either android isn't linux, or it's both linux
> and android, and we just do like we do with Posix and put the more specific one
> first in the version lists.
Android is both 'linux' and 'Android'. gdc currently defines both version(linux) and version(Android) for it. It's not posix though.

But that's not the problem. The problems are like this: Android's thread implementation is not posix compliant, but it supports most posix threads functions. So what to do with core.sys.posix.pthread?
Sure we could just add another version(Android) block and include everything there, but if we're going to duplicate all the function definitions, enums, etc (like we already do for BSD, OSX, 'linux') anyway, why put it all in a single file? Android is just one example, there will be many more when gdc gets ported to different architectures.

Kagamin suggested to add complete glibc, bionic, etc bindings to deimos, then core.* could publically import the approriate modules from deimos. Seems like a good idea to me. We'd need some way to determine the used C library with static if(), to import the correct files, but the rest seems simple enough. Technically this means druntime depends on deimos, but those are only bindings which could be compiled/shipped with druntime.

-- 
Johannes Pfau

_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

February 26, 2012
Just a few quick ideas, I must admit that I didn't really think the issue through yet:

On 26 Feb 2012, at 14:32, Johannes Pfau wrote:
> Kagamin suggested to add complete glibc, bionic, etc bindings to deimos, then core.* could publically import the approriate modules from deimos. […]

This poses a question though: If we already have the files in Deimos, why offer the interfaces through druntime at all (besides backwards compatibility)? Which parts of Posix, … should be offered through core.*?

> Seems like a good idea to me. We'd need some way to determine the used C library with static if(), to import the correct files, […]

Just a -version switch defined in dmd.conf/sc.ini (resp. ldc.conf, or the GDC equivalent) seems like a fine solution for me. It would probably mapped to an enum by a druntime module for easier handling, and if not present, we could simply print out a pragma(msg) and default to glibc where appropriate to offer a smooth transition for people who don't routinely upgrade their DMD config files.

> Technically this means druntime depends on deimos, but those are only bindings which could be compiled/shipped with druntime.

Note aside: Deimos bindings never ever need to be compiled. If they do require linking in symbols besides the C library itself, it's a bug (at least in my opinion).


David
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

February 26, 2012
On Sunday, February 26, 2012 15:13:30 David Nadlinger wrote:
> Just a few quick ideas, I must admit that I didn't really think the issue through yet:
> 
> On 26 Feb 2012, at 14:32, Johannes Pfau wrote:
> > Kagamin suggested to add complete glibc, bionic, etc bindings to deimos, then core.* could publically import the approriate modules from deimos. […]
> 
> This poses a question though: If we already have the files in Deimos, why offer the interfaces through druntime at all (besides backwards compatibility)? Which parts of Posix, … should be offered through core.*?

I think that it's more of an issue of "why are they in deimos?" They should all be in druntime. The same goes of for any OS bindings. For instance, the current plan is for all of the Win32 API bindings to be put into druntime. Why wouldn't we do the same with glibc?

- Jonathan M Davis
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

February 26, 2012
Am 26.02.2012 15:13, schrieb David Nadlinger:
>> Technically this means druntime depends on deimos, but those are only bindings which could be compiled/shipped with druntime.
>
> Note aside: Deimos bindings never ever need to be compiled. If they do require linking in symbols besides the C library itself, it's a bug (at least in my opinion).

There are a lot of excessive macros in C librarys and since there's no
preprocessor in D, they'll mostly be covered by wrapper functions. So
commonly deimos isn't just a thin binding, it often adds it's own symbols.
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

February 26, 2012
On 26 Feb 2012, at 15:41, mta`chrono wrote:
> Am 26.02.2012 15:13, schrieb David Nadlinger:
>> Note aside: Deimos bindings never ever need to be compiled. If they do
>> require linking in symbols besides the C library itself, it's a bug
>> (at least in my opinion).
>
> There are a lot of excessive macros in C librarys and since there's no
> preprocessor in D, they'll mostly be covered by wrapper functions. So
> commonly deimos isn't just a thin binding, it often adds it's own symbols.

This doesn't preclude the possibility of a »header only« interface – you can simply make the macro translations template functions, and they'll always be emitted during compilation, instead of being linked in.

I think I'm not the only one preferring to avoid the need for linking in extra libs – If I remember correctly, the original Deimos manifesto by Walter had a similar suggestion/requirement as well.

By the way, the manifesto seems to have disappeared with the move to D-Programming-Deimos, we should probably add it to a dlang.org page. This page could also include short tips for writing bindings, like the above.


David
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

February 26, 2012
On 25 February 2012 17:31, Johannes Pfau <johannespfau@googlemail.com> wrote:
> This is probably less a problem for DMDs druntime, but we hit this issue with gdc and the android port now, so I thought I'll also post this message here, maybe someone has a good idea.
>
> Android uses a custom C library (Bionic) which is not 100% Posix compatible. With the current approach of supporting different systems using version() blocks, this will lead to lots of changes in all the core/* files. And it will get much worse once we try to support other C libraries (newlib for DS/Wii homebrew, uclibc/dietlibc/eglibc for embedded linux, etc). The current aproach is already broken for Android, as druntime assumes version(linux) --> glibc which is not true. One such broken example is the usage of the glibc "backtrace" function.
>
> Here's the original message sent to the D.gnu newsgroup:
>
> ________________________________
> As recently discussed in a pull request it would be great if we could
> make it easier to port druntime to different architectures. Special
> casing every C library, every architecture and every OS using version
> blocks could lead to difficult to maintain code, so we need a better
> solution.
>
> As far as I can see, the biggest differences are caused by different C libraries, not by different architectures (except 32bit vs 64 bit differences). For example glibc headers seem to be very similar for arm and x86, but bionic vs. glibc brings more differences. Bionic initially didn't support anything wchar_t related, so core.stdc.wchar_ and core.stdc.wctype couldn't work with android at all. And C libraries vary even more in the subset of posix functionality they support.
>
> We need a directory scheme to support
> * Different C libraries
>   * on different OS (glibc/bsd glibc/linux)
>   * on the same OS (glibc on linux, bionic on linux, uclibc on
>     linux, ...)
> * Different architectures (ARM, X86, MIPS, PPC, SH4, ...)
>
> I propose the following directory layout, but of course better solutions are appreciated:
>
> druntime
> |-core
> |---stdc
> |---sync
> |---sys
> |-----posix
> |-gc
> |-gcstub
> |-rt
> |-gcc
> |---arch
> |-----glibc
> |-------core
> |---------stdc
> |---------sync
> |---------sys
> |-----------posix
> |-----bionic
> |-------stdc
> |-------sync
> |-------core
> |---------sys
> |-----------posix
> |-----newlib
> |-------stdc
> |-------sync
> |-------core
> |---------sys
> |-----------posix
>

So I gather from what your proposing that ie: core.stdc.stdio will look like the following?

module core.stdc.stdio;

version (GLibc)
  public import gcc.glibc.core.stdc.stdio;
else version (Bionic)
  public import gcc.bionic.core.stdc.stdio;
// etc.


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
_______________________________________________
D-runtime mailing list
D-runtime@puremagic.com
http://lists.puremagic.com/mailman/listinfo/d-runtime

« First   ‹ Prev
1 2