[D-runtime] Supporting different C libraries and architectures

Sean Kelly sean at invisibleduck.org
Sat Feb 25 11:52:07 PST 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 at 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 at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/d-runtime


More information about the D-runtime mailing list