www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - linker warnings and errors with bindbc-glfw

reply Dennis <dkorpel gmail.com> writes:
I'm trying the static bindings for glfw of bindbc on Windows, 
using the pre-compiled .lib files from the lib-vc2015 folder in 
the official download. 
(http://code.dlang.org/packages/bindbc-glfw)
With LDC using the Microsoft MSCV linker, everything works. I can 
either add this:

app.d:
```
version(X86)    pragma(lib, "lib32/glfw3.lib");
version(X86_64) pragma(lib, "lib64/glfw3.lib");
```

Or this:

dub.sdl:
```
libs "lib32/glfw3" platform="windows-x86"
libs "lib64/glfw3" platform="windows-x86-64"
```

And then these:
dub --arch=x86 --compiler=ldc2
dub --arch=x86_64 --compiler=ldc2

Both work, albeit with a lot of warnings:
libcmt.lib(initializers.obj) : warning LNK4098: defaultlib 
'msvcrt.lib' conflicts with use of other libs; use 
/NODEFAULTLIB:library
glfw3.lib(init.c.obj) : warning LNK4217: locally defined symbol 
___stdio_common_vsprintf imported in function __glfwInputError
glfw3.lib(wgl_context.c.obj) : warning LNK4049: locally defined 
symbol _calloc imported

I omitted about 30 more LNK4049 warnings.
With --link-internally, I get the same warnings. It finishes 
linking, but running results in a "Program exited with code 
-1073741819".

With dmd, I have less luck. First of all, I have to use 
--arch=x86_mscoff, or else it uses OPTLINK for 32-bit which only 
handles OMF, though ldc says "Unsupported architecture: 
x86_mscoff" when I do that, which is inconsistent.

But that's just a minor annoyance, the error is that there are 82 
unresolved externals.

glfw3.lib(win32_init.c.obj) : error LNK2019: unresolved external 
symbol __imp__RegisterDeviceNotificationW 12 referenced in 
function _createHelperWindow
glfw3.lib(win32_init.c.obj) : error LNK2019: unresolved external 
symbol __imp__CreateWindowExW 48 referenced in function 
_createHelperWindow
...

I think dmd uses the same linker as LDC, but I don't know how to 
tell for sure.

I mentioned a lot of issues in this post, but I'll be happy if I 
can compile it with dmd. Making it work with lld and removing the 
warnings are also nice, but I can live with Microsoft's linker 
and some command line clutter. Any help will be appreciated.
Nov 09 2018
next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Friday, 9 November 2018 at 18:19:22 UTC, Dennis wrote:
 [...]
I just noticed in the section about the static version: "This requires the GLFW development package be installed on your system at compile time." http://code.dlang.org/packages/bindbc-glfw I don't see where I can install the 'development package'. There is a download of development files, but I don't see how having the source code stored somewhere helps linking with the library.
Nov 09 2018
parent Mike Parker <aldacron gmail.com> writes:
On Friday, 9 November 2018 at 19:06:56 UTC, Dennis wrote:
 On Friday, 9 November 2018 at 18:19:22 UTC, Dennis wrote:
 [...]
I just noticed in the section about the static version: "This requires the GLFW development package be installed on your system at compile time." http://code.dlang.org/packages/bindbc-glfw I don't see where I can install the 'development package'. There is a download of development files, but I don't see how having the source code stored somewhere helps linking with the library.
The zip file with the precompiled libs *is* the development package on Windows. Linux package managers tend to distinguish between the end-user packages and developer packages for libraries.
Nov 09 2018
prev sibling next sibling parent reply kinke <noone nowhere.com> writes:
On Friday, 9 November 2018 at 18:19:22 UTC, Dennis wrote:
 I'm trying the static bindings for glfw of bindbc on Windows, 
 using the pre-compiled .lib files from the lib-vc2015 folder in 
 the official download. 
 (http://code.dlang.org/packages/bindbc-glfw)
 With LDC using the Microsoft MSCV linker, everything works. I 
 can either add this:

 app.d:
 ```
 version(X86)    pragma(lib, "lib32/glfw3.lib");
 version(X86_64) pragma(lib, "lib64/glfw3.lib");
 ```

 Or this:

 dub.sdl:
 ```
 libs "lib32/glfw3" platform="windows-x86"
 libs "lib64/glfw3" platform="windows-x86-64"
 ```

 And then these:
 dub --arch=x86 --compiler=ldc2
 dub --arch=x86_64 --compiler=ldc2

 Both work, albeit with a lot of warnings:
 libcmt.lib(initializers.obj) : warning LNK4098: defaultlib 
 'msvcrt.lib' conflicts with use of other libs; use 
 /NODEFAULTLIB:library
 glfw3.lib(init.c.obj) : warning LNK4217: locally defined symbol 
 ___stdio_common_vsprintf imported in function __glfwInputError
 glfw3.lib(wgl_context.c.obj) : warning LNK4049: locally defined 
 symbol _calloc imported

 I omitted about 30 more LNK4049 warnings.
I guess you're running LDC in a VS environment, so that it's defaulting to `-mscrtlib=libcmt`. You should be able to work around these warnings with `-mscrtlib=msvcrt` then, to link against the dynamic C runtime (DLL) instead of the static one. [`-L/NODEFAULTLIB:msvcrt.lib` should work too, if you want to link against the static one.] The real issue is that the glfw libs are apparently compiled with `/MD`, but should rather be with `/MT /Zl`, which goes for all static libs compiled with MSVC, in order not to drag in any default library (libcmt/msvcrt).
 With --link-internally, I get the same warnings. It finishes 
 linking, but running results in a "Program exited with code 
 -1073741819".
May be worth another try with the proper command line.
 With dmd, I have less luck. First of all, I have to use 
 --arch=x86_mscoff, or else it uses OPTLINK for 32-bit which 
 only handles OMF
Seems to be just causing issues for most users AFAICT, IMHO it's definitely time DMD moved to COFF by default (and shipped with 64-bit executables, and defaulted to Win64).
 though ldc says "Unsupported architecture: x86_mscoff" when I 
 do that, which is inconsistent.
That's a dub issue. LDMD supports `-m32mscoff`, mapping it to `-m32`, while LDC only supports `-m32`. But dub apparently forwards the -arch verbatim, and `x86_mscoff` is definitely no architecture recognized by LLVM. ;)
 I think dmd uses the same linker as LDC, but I don't know how 
 to tell for sure.
Run LDC or DMD with `-v`, that gives you the linker command line at the end of the output.
Nov 09 2018
parent Dennis <dkorpel gmail.com> writes:
On Friday, 9 November 2018 at 19:21:30 UTC, kinke wrote:
 May be worth another try with the proper command line.
Thank you! LDC + LD now works without warnings. On Friday, 9 November 2018 at 19:21:30 UTC, kinke wrote:
 Run LDC or DMD with `-v`, that gives you the linker command 
 line at the end of the output.
I just see this at the end of dmd -v: Linking... LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library And then the 81 unresolved externals of Windows APi functions with weird name mangling (__imp__CreateWindowExW 48, __imp__DestroyWindow 4 etc.).
Nov 09 2018
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Friday, 9 November 2018 at 18:19:22 UTC, Dennis wrote:

 Both work, albeit with a lot of warnings:
 libcmt.lib(initializers.obj) : warning LNK4098: defaultlib 
 'msvcrt.lib' conflicts with use of other libs; use 
 /NODEFAULTLIB:library
 glfw3.lib(init.c.obj) : warning LNK4217: locally defined symbol 
 ___stdio_common_vsprintf imported in function __glfwInputError
 glfw3.lib(wgl_context.c.obj) : warning LNK4049: locally defined 
 symbol _calloc imported
This is a perennial annoyance when working with static libraries precompiled with Visual Studio on Windows. Some projects are configured one way, some another.
 But that's just a minor annoyance, the error is that there are 
 82 unresolved externals.

 glfw3.lib(win32_init.c.obj) : error LNK2019: unresolved 
 external symbol __imp__RegisterDeviceNotificationW 12 
 referenced in function _createHelperWindow
 glfw3.lib(win32_init.c.obj) : error LNK2019: unresolved 
 external symbol __imp__CreateWindowExW 48 referenced in 
 function _createHelperWindow
 ...
When you link statically with a library, you have to link with all of its dependencies, too. For GLFW, you'll need User32.lib, gdi32.lib, and OpenGL32.lib, off the top of my head. Any particular reason you want to avoid the DLL?
Nov 09 2018
parent Dennis <dkorpel gmail.com> writes:
On Friday, 9 November 2018 at 19:40:15 UTC, Mike Parker wrote:
 When you link statically with a library, you have to link with 
 all of its dependencies, too. For GLFW, you'll need User32.lib, 
 gdi32.lib, and OpenGL32.lib, off the top of my head.
Aha. Now I wonder why LDC includes those dependencies and dmd doesn't. On Friday, 9 November 2018 at 19:40:15 UTC, Mike Parker wrote:
 Any particular reason you want to avoid the DLL?
Perhaps these are superficial reasons, but I just like the idea of static libraries more. - No run-time linking errors (dll not found, different version) - No function pointer loading and dereference overhead - On Windows, you tend to end up redistributing the needed .dll's anyway It seemed really simple, and on LDC it was. But if I'm about to open a big can of worms then I could stick to the dll, at least for dmd. On the other hand, I would really want to understand how all of this works. So I'm going to paint how I picture this in my head: Windows ships with: - Windows API DLL's (gdi32.dll, user32.dll etc.) - A dynamic C runtime library msvcrt.dll dmd ships with: - D headers for Windows and standard C functions - import libraries for linking to Windows dll's containing those functions - An OMF-linker - The DMC C runtime library? (IIRC, can't identify it in the lib folder) Microsoft Visual C contains: - C headers for Windows and standard C functions - import libraries - A COFF-linker - A static C runtime library libc.lib (single threaded) and libcmt.lib (multi-threaded) Now the issue is that glfw is compiled in a way that it expects the dynamic c runtime, but D compilers default to the static one. So should tell the D compiler to use -mscrtlib=msvcrt or else it will generate warnings and maybe crash (in the case of LLD). The other issue is that glfw expects the import libraries for Windows are linked in, which LDC does automatically, but dmd doesn't in my configuration for some reason. Is that a correct summary?
Nov 09 2018