Final steps for shared library support

Johannes Pfau via D.gnu d.gnu at puremagic.com
Mon May 23 04:01:10 PDT 2016


Am Sun, 22 May 2016 20:41:03 +0200
schrieb Johannes Pfau <nospam at example.com>:
> 
> 2) We have to call _d_dso_registry once from every shared library and
>    from the main executable:
>    * DMD emits a weak function _d_dso_init into every object file.
>      Additionally it adds a weak reference to this into the .ctors
>      section for every object. We could probably do this manually. But
>      this is not really portable and I don't think we can get the
>      portable DECL_CONSTRUCTOR to emit weak references.
>    * LDC also emits the weak _d_dso_init function. It emits normal
>      constructors so _d_dso_init will be called multiple times. It
> uses a static variable in _d_dso_init to detect repeated calls.
>      We could probably do this. Disadvantages: many useless
>      constructors, the source code for _d_dso_init is hardcoded in the
>      compiler and we have to hardcode the OS detection (i.e. emit
>      _d_dso_init for linux, freebsd, ...)
>    * We use the 'GCC way': The way C constructors are implemented is
>      using startup files. These are special object files linked once
>      into every shared library and executable. I've implemented &
>      tested this approach in the pull request:
>      If we link against libphobos, load
>      https://github.com/jpf91/GDC/blob/shared3/libphobos/libdruntime/libdruntime.spec
>      libdruntime.spec will then add __dshared.o to the start files, if
>      the file exists. This means:
>      * When linking with nophoboslib, __dshared.o and libdruntime.spec
>        are not used and do not have to exist (good for bare metal
> code)
>      * The spec can be redefined using GCCs spec file mechanism.
>      * If __dshared.o does not exist (maybe not needed for some OSs)
>        linking is done as usual.
>      * We can add any code we want to __dshared.o/c/d. It will be
> linked once into every shared library and executable. OS detection can
>        be done in C or D source code instead of in the compiler.
>      * Main drawback: Linking needs to be done with gdc. If a user
>        needs to link with gcc or g++ this is still possible using
>        -specs=libdruntime.spec
>      * As we need to link phobos/druntime with -nophoboslib we also
>        have to use -specs=libdruntime.spec here.


OTOH the LDC approach doesn't sound too bad either. There probably
won't be more than ~1000 modules in a shared lib and the ctor stubs we
call should be pretty cheap. I don't want the OS detection in the
compiler though. Right now the function is quite simple, but who knows
what it will look like once we support more OSs. We could probably adapt
the __entrypoint.di approach: We need to add support for
attribute(constructor, destructor, visibility) first. Then we can
translate __dshared.c into D. We'd just ship the source file and
compile it into every object file (except for -betterC).
We also have to make sure the compiler does not emit ModuleInfo for
this module. Then we can simply do this:

__dshared.d:
// No ModuleInfo for this module
module sharedinclude;

import rt.sections : useDSORegistry;

static if (useDSORegistry)
{
    @weak @hidden void __d_dso_init() {_d_dso_registry(...)}
    @weak @hidden __gshared bool started, stopped;
    // Have to somehow make sure this function does not clash with the
    // same function in other object files (i.e. C-like static)
    private @ctor @weak void startDSO()
    {
        if(started)
            return;
        started = true;
        __d_dso_init();
    }
    [...]
}

I think both solutions are OK. @Iain which one do you
prefer?


More information about the D.gnu mailing list