You don't need no stinking projects (dub version)

#dlang, code


Let’s say you want to build an application that you know will fit in a single file. Many of the scripting/automation programs fall in this category. However, the program depends on a third-party library. You think you may need to setup a “project”, and you start thinking “maybe I can just use Python for this”. But then still you are left with the task of (globally) installing the package using pip or creating a virtualenv. And if you have to “ship” this program, you are left with no choice but to ship with a dependency management tool (ie., requirements.txt or a Pipfile). With D, (specifically dub), you can have your cake and eat it too.

Show me the code!

#!/usr/bin/env dub
/+ dub.sdl:
    name "allthepythons"
    dependency "d-glob" version="~>0.3.0"
+/

import std.stdio : stdout;
import glob : glob;

void main () {
  foreach (entry ; glob("/usr/local/bin/python*")) {
    stdout.writefln("%s", entry);
  }
}

In the above program, you are using a third-party library called glob-d (you might argue, “with python, you don’t have use a third-party library for this, hah!”. Bear with me here, this is after all a made-up example!).

The #!/usr/bin/env dub hashbang tells the shell to use D’s dub package manager, to run the code that follows.

The comment section enclosed in /+ +/ is a special section meant for dub, that informs what this single-file package is called (allthepythons) and what dependencies it has (d-glob). Dub supports two data definition languages by default – json and sdl. I used sdl here, because it is easy on the eyes.

Rest of the code is easy to understand, that needs no special explanation.

Running the script is straight-forward:

$ ./allthepythons.d

/usr/local/bin/python2
/usr/local/bin/python3
... truncated ...

This is excellent for developing, testing and scripting. However, what if you need to deploy a binary to a machine that a) does not have dub installed? and/or b) does not have an internet connection to automatically download packages from the internet? (for say, security considerations). Converting the above file to a binary is easy-peasy:

$ dub build --single allthepythons.d
Performing "debug" build using dmd for x86_64.
d-glob 0.3.0: target for configuration "default" is up to date.
allthepythons ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.

You will end up with a binary named allthepythons that can then be deployed easily.

Note: In order to produce a “release” binary, add --build=release to the dub build command.

dub build --build=release --single allthepythons.d

Thanks to Aravinda K on Reddit for pointing it out!

Viva la D!

Links –