Comment #0 by alphaglosined — 2023-04-21T18:47:38Z
The compiler must have a way of differentiating between a module that is being compiled into the binary and is outside of it (i.e. in a 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 placing a requirement of a module outside of the binary to have a ModuleInfo generated for it triggered by unittests.
The cheapest way to do this for both package/build managers will be to add a second -I switch that sets the flag on a module node.
Comment #1 by kinke — 2023-04-22T19:42:41Z
Templates highly complicate matters. Little contrived example: an application with `app.d`, depending on a shared lib with `sharedlib.d`, which further depends on a `staticlib.d` static library:
app.d:
```
void foo() {
import sharedlib;
sharedFoo!();
}
```
sharedlib.d:
```
void sharedFoo()() {
import staticlib;
staticFoo!();
}
```
staticlib.d:
```
void staticFoo()() {
bar();
}
private void bar() {}
```
The staticlib.lib library contains `bar()` only. If sharedlib doesn't instantiate `staticFoo!()` itself, sharedlib.dll contains no `staticFoo` symbol, and the staticlib.obj object file isn't linked into the DLL either (provides no required symbols). So it's the actual app which contains both `sharedFoo` and `staticFoo` symbols, but still depends on the non-templated `bar` function. So the app needs to be linked against staticlib.lib too, a transitive dependency from the shared lib.
Things become interesting if `staticFoo` is instantiated and codegen'd in sharedlib.dll. Then a per-module flag doesn't suffice anymore - staticlib.d's `staticFoo()` part is linked from the shared library, but `bar()` from the static lib.
Comment #2 by alphaglosined — 2023-04-22T20:17:55Z
Am I right to understand the core problem you are describing @kinke is duplicate symbols?
If so, I am not sure how any exporting attributes could fix this scenario when you are duplicatiing including object files in your program. You're going to have hidden state that is duplicated which puts your program into an unknown state as you use it.
But that does lead to a question if a build manager detects an include + external include matching, should it error rather than pick? Because now I'm thinking that yes it should error because things are not going to do what you want.
Comment #3 by bugzilla — 2023-06-05T23:51:52Z
Please add the 'dll' keyword when creating an issue about dlls.
Comment #4 by alphaglosined — 2023-07-10T09:54:40Z
I have unfortunately hit a problem with LDC. There was a type declared in a -betterC DLL, this type had its __initZ symbol exported. It was referenced by a TypeInfo generated for an executable that depended on that DLL. The __initZ symbol was undefined. This situation was very easy to trigger.
The workaround was to use the dllimport override flag in the executable to force it to see the __initZ symbol. Of course, this means users of my code will have to manually add this switch.
My proposal for this switch, would have allowed dllimport mode to be placed upon the DLL module, as it was known to be external to the binary.
This gives me more confidence in saying, this will be a requirement if we ever want to get shared library support to 100% and not require the override switches to be used under normal circumstances.
https://github.com/ldc-developers/ldc/issues/4434
Comment #5 by robert.schadek — 2024-12-13T19:28:22Z