Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

druntime: replaces top level version(..) branching by tags #15822

Closed
wants to merge 113 commits into from

Conversation

denizzzka
Copy link
Contributor

@denizzzka denizzzka commented Nov 16, 2023

(Reduced squashed version of this PR is here: #15887)

Hi!

I propose to reorganize OS- and arch- related druntime code as in this PR.

For example, druntime/src/core/sync/event.d file in ~master actually contains 2 version of sources: each method contains implementations for Windows and for Posix. This file can be reorganized as 3 separate files (two inside of new config/ directory) by this way:

druntime/config/windows/core/sync/event.d
druntime/config/posix/core/sync/event.d
druntime/src/core/internal/event_tests.d

Now these files is not contain D version(..) branches - build script switches these files using "tags".

For example, if we build for a Linux for x86 build routine can use these 3 tags: linux,posix,x86. And appropriate files (in this case druntime/config/posix/core/sync/event.d) from these hierarchies will be applied as sources and include files. (File event_tests.d is not placed into this config/ "tags hierarchy" and will be compiled-in in all cases.)

In other words, proposed approach replaces top level version(..) branches by a separate files which unioned by "tags".

Advantages of this approach:

  • It will help us to avoid difficult branching schemas and helps to separate common logic and OS- or arch- related stuff.

  • This approach itself encourages (forces) us to reorganize all druntime code into "tagged" and this will lead to convient use of this code by various types OSes and systems, including custom OSes (not presented in the current "official" sources)

  • It helps to clarify division between minimum required code for a druntime and custom bindings for every user (What we did not get from a separation of druntime and Phobos once upon a time)

  • It becomes impossible to forget default static assert fuse in such cases:

    version (Posix) {
    ...
    }
    else version (Windows) {
    ...
    }
    else
        static assert(false, "Is not implemented on this platform. Easy to forgot this fuse.");
  • druntime is a special sort of software and (if it is need) this approach will help to maintain duplicated nature of druntime's bindings: having (almost) identical files is more convenient than have files containing (almost) identical blocks. Moreover, the presence of such files itself will be a signal that some kind of deduplication is possible again. Currently everything is hidden under the name of one file (~master tgmath.d as example of such trouble)

  • In some cases it opens ability to import modules with foreign data structures on non-native OSes. It will be possible to remove module "guards" like version (Linux): at start of the modules and your Windows app will be able to import Linux data structures. In the future, it will be much easier to get rid of all from this when all OS-specific code will be moved to config/ hierarchy.

  • I think in the future this approach eliminates tons of these identical version lines in favor to using tags (and, maybe, enums in some cases):

version (AArch64) version = ARM_Any;
version (ARM)     version = ARM_Any;
[...]
version (X86)     version = X86_Any;
version (X86_64)  version = X86_Any;
  • Another options to solve problem is more painful:

I already asked community about supporting of embedded/rare OSes by additions of such code into almost every entry inside of druntime (community was against it):

version (ExternalImpl)
{
    public import external.core.event : Event;
}
else
struct Event
{

Now I’m also against it: it turned that, in addition to such mass additions to the code, qualifiers protected and package need to be changed to public in many places

(Also, if we talk about embedded systems, we can just wait and someone will write druntime for embedded. But even the practice of a simpler language C has shown that huge community has been writing there C runtimes newlib or picolibc from scratch for decades. I think we can't afford this, thus we forced to use one druntime for everything. So, we must deal with current official sources)

  • Tags is easier to rename: they don’t go anywhere beyond druntime. If we ever decide that we will have a filesystem_support tag or a multithreading_support tag (for example, imagine subset of OSes without filesystem), then there will not be a problem to implementing it. There will no need to change source files, just move it within confing/ hierarchy to appropriate config/filesystem_support/ directory to more fine granulation.

  • It provides a way to build druntime not only for OSes and libc which are predefined in the current druntime sources: end user will be able to specifiy his own tags, combine it with already defined by official druntime sources and provide his own config/ hierarchies. This is critical for supporting arbitrary OSes and non-OS environments (I think this is the only realistic way to provide druntime for embedded software and this is my main motivation)

  • It will become easier to keep eyes of source codes related to any subsystem: interested will be able to subscribe to their favorite druntime/config/cool_but_rarely_used_os/ section and monitor changes

Disadvantages:

  • Additional build script

  • What about other compilers?

This is how tags support can be implemented for ldc2 (CMake):
https://github.com/opendlang/opend/pull/24/files#diff-d55d21ac9c6461b7058d75699e8733f4a93b60d70bd216138b5dae2612715066

============
Old version of origin text:

Proof of concept described at https://forum.dlang.org/post/ppnylqbaadkqwmulgoam@forum.dlang.org

@ibuclaw That's what I meant

For demo purposes druntime files llmath.d and tgmath.d placed into new "tagged" sources dirs. Each file is splitted into pieces related to specified tags

@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @denizzzka! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#15822"

@ibuclaw
Copy link
Member

ibuclaw commented Nov 16, 2023

Not sure whether copying the files as needed in dmd really benefits gdc or ldc which have different configure/make files. Downstreaming becomes tricky.

The main argument being that D has a module system, use it.

@denizzzka
Copy link
Contributor Author

denizzzka commented Nov 16, 2023

Not sure whether copying the files as needed in dmd really benefits

Copying is gone in the current version of PR

gdc or ldc which have different configure/make files. Downstreaming becomes tricky.

All magic is locked inside of cp_tagged_hier.sh script

At the final stage all compiler-related additions may be placed into ./impr/ as separate files

The main argument being that D has a module system, use it

I tried - it totally doesn't work for custom and embedded systems: druntime source comes to necessity of adding something like import external_backend.core.blah_blah into ~each druntime source file

@ibuclaw
Copy link
Member

ibuclaw commented Nov 16, 2023

Not sure whether copying the files as needed in dmd really benefits gdc or ldc which have different configure/make files. Downstreaming becomes tricky.

All magic is locked inside of cp_tagged_hier.sh script

GDC uses ./configure, so not shareable.

Anyway, @kinke was also need a look over as ldc would be forced to adjust their build/cmake files too.

druntime/posix.mak Outdated Show resolved Hide resolved
@denizzzka denizzzka changed the title druntime: tagged versions branching druntime: replaces top level version(..) branching by tags Dec 5, 2023
@denizzzka
Copy link
Contributor Author

Closing in favor to #15887

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants