I want to statically link my D library (which uses dub) with my C++ app.
I've followed the instructions on the wiki to successfully manually link the example.
But, I have my own library that uses dub, and I can't figure out how to make it output something I link to using cl
.
Let me show you what I mean (example code from the wiki, but with dub added):
Project directory:
E:\Projects\foo
│ main.c
│
└───libadd
│ dub.json
│ libadd.lib
│
└───source
main.d
main.c:
#include <stdio.h>
// Defined in dlib.d
int add(int, int);
int main(int argc, char ** argv) {
int result = add(40, 2);
printf("The result is: %i\n", result);
return 0;
}
libadd/dub.json:
{
"name": "libadd",
"targetType": "staticLibrary",
"mainSourceFile": "libadd.d",
"buildOptions": [
"verbose"
]
}
libadd/source/libadd.d:
module libadd;
extern (C) int add(int a, int b) {
return a + b;
}
// Only needed on Linux.
extern (C) void _d_dso_registry() {}
Compiling and linking using instructions from the wiki works fine:
e:\Projects\foo> dmd -c -v -m32mscoff -betterC libadd/source/libadd.d
binary C:\opt\D\dmd2\windows\bin\dmd.exe
version v2.071.1
config C:\opt\D\dmd2\windows\bin\sc.ini
parse libadd
importall libadd
import object (C:\opt\D\dmd2\windows\bin\..\..\src\druntime\import\object.d)
semantic libadd
semantic2 libadd
semantic3 libadd
code libadd
function libadd.add
function libadd._d_dso_registry
e:\Projects\foo> cl /nologo /Fefoo.exe main.c libadd.obj
main.c
e:\Projects\foo> foo.exe
The result is: 42
But how do I do this with dub? I noticed that while manual compiling with dmd
produces an .obj
, dub
produces an .lib
. According to professor Google, .lib
is a static library on Windows, but I can't link to it. I already set targetType
to staticLibrary
in dub.json
.
I also noticed that the dmd
flags -m32mscoff
and -betterC
have no corresponding buildOptions
setting in dub.json. I'm not sure how to compensate, though.
e:\Projects\foo> cd libadd
e:\Projects\foo\libadd> dub
Performing "debug" build using dmd for x86.
libadd ~master: building configuration "library"...
binary C:\opt\D\dmd2\windows\bin\dmd.exe
version v2.071.1
config C:\opt\D\dmd2\windows\bin\sc.ini
parse libadd
importall libadd
import object (C:\opt\D\dmd2\windows\bin\..\..\src\druntime\import\object.d)
semantic libadd
semantic2 libadd
semantic3 libadd
code libadd
function libadd.add
function libadd._d_dso_registry
library .dub\build\library-debug-windows-x86-dmd_2071-2DA862E35C1BEDC80780CBC1AB5F7478\libadd.lib
Target is a library. Skipping execution.
e:\Projects\foo\libadd> cd ..
e:\Projects\foo> cl /nologo /Fefoo.exe main.c libadd/libadd.lib
main.c
libadd/libadd.lib : fatal error LNK1136: invalid or corrupt file
How do I statically link my D library that uses dub, with a C++ app?
After some trouble I figured it out.
It turns out, -m32mscoff
is important, and it's required for 32-bit. Compiling and linking for 64-bit works fine as-is.
Add into dub.json
:
"dflags-windows-x86-dmd": [
"-m32mscoff"
]
Even though dub
passes -m32
to dmd
, it's -m32mscoff
that's needed. You can now link with cl
as normal.