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

Regression: Cannot create DLL with static runtime on Windows anymore #2568

Closed
p0nce opened this issue Jan 17, 2023 · 9 comments
Closed

Regression: Cannot create DLL with static runtime on Windows anymore #2568

p0nce opened this issue Jan 17, 2023 · 9 comments

Comments

@p0nce
Copy link
Contributor

p0nce commented Jan 17, 2023

System information

  • dub version: dub 1.31
  • OS Platform and distribution: Windows 11
  • compiler version LDC 1.30.0 with the newer dub, Visual C++ 2019

Bug Description

Previously with DUB 1.29.0, the way to create DLL that statically link to msvc was to add the following flags:

    "dflags-windows-ldc": ["-mscrtlib=libcmt","-fvisibility=hidden", "-link-defaultlib-shared=false"]

Now "-link-defaultlib-shared=false" create untractable errors, and we cannot statically link the MSVC runtime anymore.
This is massively disrupting, as statically linking the C and D runtime is necessary for portability, this is a lesson we learned over and over. So we really do not want a shared runtime, either C or D runtime, this is a nightmare come true for us.

How to reproduce?

dub.json

{
    "name": "reprodll",
    "importPaths": [ "." ],
    "sourcePaths": [ "." ],
    "targetType": "dynamicLibrary",
    "dflags-windows-ldc": ["-mscrtlib=libcmt","-fvisibility=hidden", "-link-defaultlib-shared=false"]
}

arpejoe.d

import core.sys.windows.windef;
import core.sys.windows.dll;
export extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
    return true;
}

Type: $ dub on Windows and see:
reprodll.obj : error LNK2019: symbole externe non résolu __imp__D4core3sys7windows3dll12__ModuleInfoZ référencé dans la fonction ldc.dllimport_relocation

Expected Behavior

No problem in DUB 1.29.0, this is a regression.
It should be possible, and even easier, to create a static library without a harmful dependency on druntime-ldc-shared.dll

Logs

Using DUMPBIN.exe, the faulty DLL has the following import section:

Microsoft (R) COFF/PE Dumper Version 14.00.24245.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file reprodll.bad.dll

File Type: DLL

  Section contains the following imports:


    druntime-ldc-shared.dll
             18000D218 Import Address Table
             180016030 Import Name Table
                     0 time date stamp
                     0 Index of first forwarder reference

                           0 _d_dso_registry
                           0 _D4core3sys7windows3dll12__ModuleInfoZ
@rikkimax
Copy link
Contributor

Compile + link commands:

C:\Tools\D\ldc2-1.30.0-beta1-windows-multilib\bin\ldc2.exe -fvisibility=public -dllimport=all -mscrtlib=libcmt -fvisibility=hidden -link-defaultlib-shared=false -c -ofC:\Users\alpha\AppData\Local\dub\cache\reprodll\~master\build\library-debug-windows-x86_64-ldc_v1.30.0-beta1-DCC155688B4EF35EFFB88CAB356AEEA4527ADA01A88B83CD6678F32B75C4C150\reprodll.obj -d-debug -g -w --oq -od=C:\Users\alpha\AppData\Local\dub\cache\reprodll\~master\build\library-debug-windows-x86_64-ldc_v1.30.0-beta1-DCC155688B4EF35EFFB88CAB356AEEA4527ADA01A88B83CD6678F32B75C4C150/obj -d-version=Have_reprodll -I. arpejoe.d -vcolumns

C:\Tools\D\ldc2-1.30.0-beta1-windows-multilib\bin\ldc2.exe -ofC:\Users\alpha\AppData\Local\dub\cache\reprodll\~master\build\library-debug-windows-x86_64-ldc_v1.30.0-beta1-DCC155688B4EF35EFFB88CAB356AEEA4527ADA01A88B83CD6678F32B75C4C150\reprodll.dll C:\Users\alpha\AppData\Local\dub\cache\reprodll\~master\build\library-debug-windows-x86_64-ldc_v1.30.0-beta1-DCC155688B4EF35EFFB88CAB356AEEA4527ADA01A88B83CD6678F32B75C4C150\reprodll.obj -mscrtlib=libcmt -link-defaultlib-shared=false -shared -g

@rikkimax
Copy link
Contributor

rikkimax commented Jan 17, 2023

The commands look ok. I think dub is doing the right thing. The problem appears at least initially to be on ldc's end.

Specifically: __imp__D4core3sys7windows3dll12__ModuleInfoZ that implies the ModuleInfo for core.sys.windows.dll was not exported. But it was expected to be. That module for its module constructors hasn't changed in 7 years so we can rule that out. Removing the import to that module should of course fix it, but you'll end up with issues elsewhere.

@kinke thoughts?

@kinke
Copy link
Contributor

kinke commented Jan 17, 2023

See #2396 (comment) - in your case, you'd need to set DFLAGS=-fvisibility=hidden -dllimport=none for the dub invocation (and specify the build type explicitly, e.g., dub … --build=debug). IIRC, the DFLAGS are mainly needed to make sure these flags apply to all dub dependencies too; but feel free to see if adding -dllimport=none as dub dflags is sufficient in your case.


This was changed in #2412. I know it's annoying for DLLs linking druntime+Phobos statically, but it made regular DLLs linking against druntime+Phobos DLLs (the default behavior) work out of the box, just like for Posix platforms.

@p0nce
Copy link
Contributor Author

p0nce commented Jan 17, 2023

Thanks. But honestly it is very curious to me why one would want to generate any software with such drastic runtime dependencies. Go binaries are famously self-contained. It is the third time this is changed in D without too much warnings. Arguably the experience of using D for any kind of plugins is worse now.

@p0nce
Copy link
Contributor Author

p0nce commented Jan 17, 2023

FYI: this is not the first time DUB emits non-sensical flags, see for example #647 then patched with 6447a6c
DUB enforced a flag that then couldn't be avoided: #647 the flag was removed afterwards

See also: #166 where DUB considered only one use case.
Same story: unavoidable flag.

I think in that case it's the default in LDC which should be changed, not the flags emitted by DUB. It is the same that those above issues in my opinion. Wouldn't it would be completely normal to have -fvisibility=public and -dllimport=all be the default in LDC if -shared is provided ? And then DUB would not need to emit those flags at all. It certainly doesn't do the right thing here.

@kinke
Copy link
Contributor

kinke commented Jan 17, 2023

Wouldn't it would be completely normal to have -fvisibility=public and -dllimport=all be the default in LDC if -shared is provided ?

That is the case. But dub separates compiling and linking (generally a good thing), so this default LDC behavior is mimicked for compilation in #2412. -shared implies 'link to a DLL', so can't be used for compiling only.

But honestly it is very curious to me why one would want to generate any software with such drastic runtime dependencies.

The deps are there anyway, it's just a question of linking statically or dynamically. Dynamically is the newish default behavior with LDC on Windows - because it's a general requirement when using a process with multiple D binaries (same story on Posix, where -link-defaultlib-shared was the default for ages). Plugin DLLs (or Posix .{so,dylib}) with static druntime+Phobos are an exception and only work under very specific circumstances. It just happened to be the only option on Windows for a long time, until LDC got druntime+Phobos DLL support last year.

@MrcSnm
Copy link
Contributor

MrcSnm commented Jan 18, 2023

System information

  • dub version: dub 1.31
  • OS Platform and distribution: Windows 11
  • compiler version LDC 1.30.0 with the newer dub, Visual C++ 2019

Bug Description

Previously with DUB 1.29.0, the way to create DLL that statically link to msvc was to add the following flags:

    "dflags-windows-ldc": ["-mscrtlib=libcmt","-fvisibility=hidden", "-link-defaultlib-shared=false"]

Related to my issue #2560

@p0nce
Copy link
Contributor Author

p0nce commented Jan 18, 2023

@MrcSnm mmm that doesn't sound related, "dependencies-xxxx" was maybe recently supported, but historically that didn't work previously. Not sure what are the DUB capabilities there.

@p0nce
Copy link
Contributor Author

p0nce commented Jan 30, 2023

We are able to workaround with DFLAGS, I just wanted to note that lot of people (probably north of hundreds of thousands!) use such static D DLLs with no runtime dependencies in the wild, this is not a use case that has no interest even if it "shouldn't work", or so I hear since 7 years. It works perfectly if you don't use the runtime facilities. Even though it's nice to finally be able to host D dll in D host with runtime enabled on Windows!

@p0nce p0nce closed this as completed Jan 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants