February 26, 2012 Re: [D-runtime] Supporting different C libraries and architectures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | It's not much less of a problem for DMD than any other compiler given that many, if not all, of the same problems crop between windows, linux, freebsd, and osx -- even if they are all x86 at the moment. Only one of those is a glibc based platform. Among the non-windows platforms, all of them strive for some level of posix compatibility. The major differences are more "what subset of posix" not "I did big parts of the posix apis differently". I believe that exposing completely separate trees for each combination of platform and libc implementation is likely to lead to major pain down the road. For what it's worth, I'm not extrapolating based purely on dmd's current state. I've worked with nearly every flavor of unix at one point in time or another, porting large code bases among them. I do agree that parts of druntime (and almost certainly phobos too) conflate issues and use the occasional api that isn't part of posix. Those are more the exception than the rule and are likely fairly easy to clean up. The classic example is indeed backtrace. It's use is both non-portable (though man it's a nice api to have) across libc's but also very well isolated to one call back function. Additionally, where it doesn't exist, it almost certainly would be better to implement behind a similarly named function call rather than a version block per platform right there in the exception handling code. My 2 cents, Brad On 2/25/2012 9:31 AM, Johannes Pfau 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 approach 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 Re: [D-runtime] Supporting different C libraries and architectures | ||||
---|---|---|---|---|
| ||||
Posted in reply to mta`chrono | As long as these symbols are extern (D) I don't think this is a problem. On Feb 26, 2012, at 6:41 AM, mta`chrono <chrono@mta-international.net> wrote: > 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 _______________________________________________ D-runtime mailing list D-runtime@puremagic.com http://lists.puremagic.com/mailman/listinfo/d-runtime |
February 27, 2012 Re: [D-runtime] Supporting different C libraries and architectures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Brad Roberts | On Sun, 26 Feb 2012 21:30:33 +0100, Brad Roberts <braddr@puremagic.com> wrote: > It's not much less of a problem for DMD than any other compiler given that many, if not all, of the same problems crop > between windows, linux, freebsd, and osx -- even if they are all x86 at the moment. Only one of those is a glibc based > platform. Among the non-windows platforms, all of them strive for some level of posix compatibility. The major > differences are more "what subset of posix" not "I did big parts of the posix apis differently". I believe that > exposing completely separate trees for each combination of platform and libc implementation is likely to lead to major > pain down the road. For what it's worth, I'm not extrapolating based purely on dmd's current state. I've worked with > nearly every flavor of unix at one point in time or another, porting large code bases among them. > > I do agree that parts of druntime (and almost certainly phobos too) conflate issues and use the occasional api that > isn't part of posix. Those are more the exception than the rule and are likely fairly easy to clean up. The classic > example is indeed backtrace. It's use is both non-portable (though man it's a nice api to have) across libc's but also > very well isolated to one call back function. Additionally, where it doesn't exist, it almost certainly would be better > to implement behind a similarly named function call rather than a version block per platform right there in the > exception handling code. > > My 2 cents, > Brad > I agree, keeping different trees in sync will create more issues than fixing the few functions. _______________________________________________ D-runtime mailing list D-runtime@puremagic.com http://lists.puremagic.com/mailman/listinfo/d-runtime |
February 27, 2012 Re: [D-runtime] Supporting different C libraries and architectures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Iain Buclaw | Am 26.02.2012 18:10, schrieb Iain Buclaw: > 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. > > Yep, that was my initial idea. It's maybe too complicated though. The other solution is to remove the toplevel core/stdc and core/sys files and create those modules in a subdirectory for every c library. We could then just compile in the correct directory: druntime |-core |---atomic.d (generic files) |---bitop.d |---[...] |-gc |-gcstub |-rt |-libdc |---glibc |-----core |-------sys |-------stdc |---bionic |-----core |-------sys |-------stdc |---newlib |-----core |-------sys |-------stdc -- Johannes Pfau _______________________________________________ D-runtime mailing list D-runtime@puremagic.com http://lists.puremagic.com/mailman/listinfo/d-runtime |
February 27, 2012 Re: [D-runtime] Supporting different C libraries and architectures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | On 27 February 2012 09:16, Johannes Pfau <johannespfau@googlemail.com> wrote: > Am 26.02.2012 18:10, schrieb Iain Buclaw: > >> 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. >> >> > Yep, that was my initial idea. It's maybe too complicated though. The other solution is to remove the toplevel core/stdc and core/sys files and create those modules in a subdirectory for every c library. We could then just compile in the correct directory: > > druntime > |-core > |---atomic.d (generic files) > |---bitop.d > |---[...] > |-gc > |-gcstub > |-rt > |-libdc > |---glibc > |-----core > |-------sys > |-------stdc > |---bionic > |-----core > |-------sys > |-------stdc > |---newlib > |-----core > |-------sys > |-------stdc > > -- > Johannes Pfau > I think that is fine for the structure of the build directories, however I feel strongly that they should not be installed in such a structure. To take your example: druntime |-core |---atomic.d (generic files) |---bitop.d |---[...] |-gc |-gcstub |-rt For the file structure below - when building for glibc, the make file would have -I libdc/glibc in it's DFLAGS (or compile all relevant sources in one go) - so libdc/glibc/core/stdc/stdio.d would still be declared as 'module core.stdc.stdio;' When running 'make install' - the build gets the correct sources and puts them in their true locations. |-libdc |---glibc |-----core // Installed in /usr/include/d2/core |-------sys // Installed in /usr/include/d2/core/sys |-------stdc // Installed in /usr/include/d2/core/stdc |---bionic |-----core // Installed in /usr/include/d2/core |-------sys // Installed in /usr/include/d2/core/sys |-------stdc // Installed in /usr/include/d2/core/stdc |---newlib |-----core // Installed in /usr/include/d2/core |-------sys // Installed in /usr/include/d2/core/sys |-------stdc // Installed in /usr/include/d2/core/stdc The idea being that bionic/newlib packages are not shipped with glibc releases. The complexity here would be a minor alternation to the way the current build process is done, and will require *no change* in either existing user code or how the druntime library is written. Regards -- 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 |
February 27, 2012 Re: [D-runtime] Supporting different C libraries and architectures | ||||
---|---|---|---|---|
| ||||
Posted in reply to Iain Buclaw Attachments:
| Am 27.02.2012 11:36, schrieb Iain Buclaw: > I think that is fine for the structure of the build directories, however I feel strongly that they should not be installed in such a structure. > > To take your example: > > druntime > |-core > |---atomic.d (generic files) > |---bitop.d > |---[...] > |-gc > |-gcstub > |-rt > > For the file structure below - when building for glibc, the make file would have -I libdc/glibc in it's DFLAGS (or compile all relevant sources in one go) - so libdc/glibc/core/stdc/stdio.d would still be declared as 'module core.stdc.stdio;' > > When running 'make install' - the build gets the correct sources and puts them in their true locations. > > |-libdc > |---glibc > |-----core // Installed in /usr/include/d2/core > |-------sys // Installed in /usr/include/d2/core/sys > |-------stdc // Installed in /usr/include/d2/core/stdc > |---bionic > |-----core // Installed in /usr/include/d2/core > |-------sys // Installed in /usr/include/d2/core/sys > |-------stdc // Installed in /usr/include/d2/core/stdc > |---newlib > |-----core // Installed in /usr/include/d2/core > |-------sys // Installed in /usr/include/d2/core/sys > |-------stdc // Installed in /usr/include/d2/core/stdc > > > The idea being that bionic/newlib packages are not shipped with glibc releases. > > > The complexity here would be a minor alternation to the way the current build process is done, and will require *no change* in either existing user code or how the druntime library is written. > > > Regards > That's what I meant when I wrote "compile in the correct directory". Sorry, I should have explained that better. I think this is the best way to do this. I'll create a pull request soon, although I'll probably wait till we migrated to git. BTW: We can actually use submodules to easily merge changes between the different C libraries. I set up some test repositories to demonstrate this: https://github.com/jpf91/test-gdc is the base directory of druntime. It has got the |-libc |---glibc |---bionic structure, but glibc and bionic are submodules. The actual code for those is in https://github.com/jpf91/test-libc and 'bionic' and 'glibc' are linked to the matching branches in test-libc. To checkout: git clone git://github.com/jpf91/test-gdc.git git submodule init git submodule update -- Johannes Pfau |
Copyright © 1999-2021 by the D Language Foundation