Thread overview
[Issue 23850] Differentiate between a module that is in binary vs outside of binary when including -I
Apr 22, 2023
kinke
Apr 22, 2023
Richard Cattermole
April 22, 2023
https://issues.dlang.org/show_bug.cgi?id=23850

kinke <kinke@gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |kinke@gmx.net

--- Comment #1 from kinke <kinke@gmx.net> ---
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.

--
April 22, 2023
https://issues.dlang.org/show_bug.cgi?id=23850

--- Comment #2 from Richard Cattermole <alphaglosined@gmail.com> ---
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.

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

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |dll
                 CC|                            |bugzilla@digitalmars.com

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

--- Comment #3 from Walter Bright <bugzilla@digitalmars.com> ---
Please add the 'dll' keyword when creating an issue about dlls.

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

--- Comment #4 from Richard Cattermole <alphaglosined@gmail.com> ---
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

--