Shared library support: Where we are at in 2023

Richard Andrew Cattermole (Rikki) richard at cattermole.co.nz
Fri Apr 21 20:18:32 UTC 2023


Part 2 of: 
https://forum.dlang.org/post/ghsigisnciolxsiyaehu@forum.dlang.org

Rainer has been working on dmd support of DLL's, if completed 
this should fix export on Windows minus the ability to annotate 
DllImport/Internal in: https://github.com/dlang/dmd/pull/14849

So I've got a list of bugs and enhancements that'll get us 
further down the road of shared library support.

All of these feature are in my WIP export DIP, however as pretty 
much everything there could probably be implemented without the 
DIP lets start with the things I think have the greatest 
improvements in both mine and other peoples lives.

As an update to my own stuff, -betterC DLL with full D executable 
(unit testing) works even with dmd on Windows. Implementing the 
list of issues brought up here should allow anyone to repeat what 
I've done with minimal understanding of how linkers work as long 
as the appropriete symbols are annotated with export.



# Telling the compiler about symbol location

The compiler needs to know if a module is going inside of the 
binary or not (i.e. is in a dependency shared library).

1. It allows for the compiler to error if a templated symbol when 
instantiated references a non-exported symbol when the 
non-exported symbol is in another binary.
2. Allows automatic differentiation between DllImport and 
internal of symbols marked export.
3. Prevent unittests triggering the need for ModuleInfo when the 
unittest is in a module that is in an external binary.

This could be done in one of two ways, however one is the clear 
winner.

a. Use a pattern to match the full module name. This would not be 
automatic at the package/build manager level without slowing 
things down and would not be very cheap to process.
b. Use a second -I switch. This would be automatic at the 
package/build manager level and over all should be very cheap.

## Fixes:

https://issues.dlang.org/show_bug.cgi?id=22367

## Completes:

https://issues.dlang.org/show_bug.cgi?id=23850

## Removal of workaround:

ModuleInfo stubs.

https://github.com/Project-Sidero/basic_memory/blob/main/source/sidero/base/moduleinfostubs.d

## Prevents linker warnings:

https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-warning-lnk4217?view=msvc-170

https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-warning-lnk4286?view=msvc-170

This is quite an exciting possibility. Not having to mark symbols 
as DllImport/Internal will allow (in majority of cases) for these 
warnings to not occur. We will still need a way to annotate this 
information (easily solved design wise, but will leave it for 
later).

Just exporting a symbol will be enough even on Windows as long as 
the package/build manager helps out a little bit.



# Generated symbols

When the compiler generates a symbol it should always be exported 
if it has other symbols in the encapsulation unit that are 
exported or is itself exported.

Encapsulation unit in this case includes: modules, classes, 
structs, unions, template blocks.

A non-exhaustive list of symbols that should be exported:

1. TypeInfo
2. ModuleInfo
3. __init
4. __fieldDtor
5. __invariant
6. opCmp
7. opEquals
8. toHash

## Once export is fixed will fix:

https://issues.dlang.org/show_bug.cgi?id=6019

https://issues.dlang.org/show_bug.cgi?id=23177

## Removal of workaround:

Allows to get rid of majority of manual exports in one of my 
DLL's.

https://github.com/Project-Sidero/basic_memory/blob/main/msvc_exports.def

There are some symbols that are from druntime (like atomics) that 
should be fixed with annotating them with export.

_D4core6atomic__T8atomicOpVAyaa2_2d3dTlTiZQzFNaNbNiNfKOliZl

_D4core8internal11destruction__T11__ArrayDtorTS6sidero4base10containers3map17concurrenthashmap__T21ConcurrentHashMapNodeTSQCxQCt4text7unicode13readonly_utf811String_UTF8TSQEuQEq8datetime4timeQHc4iana6TZFileZQEg6BucketZQHeFNbNiNfMAQHcZv



# RTInfo should be emitted when used not on declaration

RTInfo should be emitted when used, this prevents unresolved 
external symbols with -betterC dependencies.

## Fixes:

https://issues.dlang.org/show_bug.cgi?id=23820



# Thread crt constructor

This may only apply to Windows, but have a thread C runtime 
constructor/destructor will allow us to kill off SimpleDllMain.

DllMain is a wholly optional concept in C/C++ land. There is no 
reason for it to exist in D either.

crt_constructor/destructor already serves half of its purpose, 
only left is the per-thread behavior.

There will be some other behaviors that the compiler will need to 
switch from DllMain detection to performing when -shared is 
passed. To complete this transition.

## Completes:

https://issues.dlang.org/show_bug.cgi?id=23756



# Set object files file name to be the full module name with 
package

Linkers like to de-duplicate object files. To do this, the 
cheapest way is to compare file names.

Problem is dmd is using only the base name and not the full 
package + module name.

LDC supports this as opt-in, but I argue that this should be the 
default.

It also means if you use packages if you have two modules with 
the same base name they won't conflict.

## Completes:

https://issues.dlang.org/show_bug.cgi?id=3541



More information about the Digitalmars-d mailing list