Dynamic libraries with dlang and dub

The DUB package manager for the D programming language doesn’t yet support dynamic library dependencies. How do you roll your own while waiting for this feature to land? Let’s take a look!

Let’s choose GtkD as our example.

Set up your project

Always need to start with a project, right?

$ dub init dynamic-gtk-project
$ cd dynamic-gtk-project
$ git init
$ git add dub.json source
$ git commit -m "empty project"

We don’t add any dependencies. Instead, we add gtk-d as a git submodule:

$ git submodule add https://github.com/gtkd-developers/GtkD

Now take the source code from the GtkD HelloWorld demo program and put it in your app.d. Commit it and we’re ready to move on.

Building the dynamic library

Now let’s walk through the steps by hand. We need GtkD built as a dynamic library, but DUB will build it as a static library. We’ll need to fix this:

$ cd GtkD
$ sed -i 's/"targetType": "library"/"targetType": "dynamicLibrary"/' dub.json
$ dub build gtk-d:gtkd

Wait for the build to finish and you should have a libgtkd-3.so in your current directory. Let’s copy that somewhere that makes sense:

$ cd ..
$ mkdir -p libs
$ cp GtkD/libgtk-3.so libs

You can turn this into a script trivially; just put all those commands into a file and add


at the start. Call the file prebuild.sh and add it to dub.json in "preBuildCommands".

Building your project

You’ve got a GTK+ program, and you’ve got GtkD, but you haven’t told DUB how to build your program. There are three parts:

  1. Tell dub where to find the GtkD imports you need
  2. Tell dub where to look for libraries
  3. Tell dub what libraries you need

All this is done in dub.json:

  • To find the imports, add "importPaths": ["GtkD/generated/gtkd"].
  • To find the libraries, add "lflags-posix": ["-Llibs"].
  • To add the gtk-d library, add "libs": ["gtkd-3"].

Now you can build your program!

Running your program

Running your program is only a little different from before: add env LD_LIBRARY_PATH=libs before any command that you’d use to run it.

For instance:

$ env LD_LIBRARY_PATH=libs dub run
$ env LD_LIBRARY_PATH=libs ./myapp


In my case, with Resin Browser, I had both webkit2-d and gtk-d as dependencies. My build times went down from 13 seconds to 2 seconds, and my binary size went from 96MB to 2.5MB.

The larger benefit was the compile time. When it takes over ten seconds to run your application after a one-line change, that feels terrible! I don’t want to experiment like that; I want to batch up my changes. But that means I lose context on problems the compiler shows me.

But when it only takes a couple seconds, it’s not so bad.