Dlang Setup
Everybody likes to work different. Here I describe how I work with dlang.
I rely on the install.sh script. It works at least for dmd, ldc and gdc (the three main dlang compilers). Normally I go for dmd or ldc.
As all my projects use dub basic setup is complete with that, on top are only convinient functions.
My fish shell is natively supported by install.sh so I can simply
source ~/dlang/dmd-2.*/activate.fish of the version I
would like to use.
On top of that I also have a small dub wrapper called d, that not
only makes it possible to call dub from any subfolder of a project,
but it also selects the compiler version based on a
.dlang-version file that is searched for till the root
of the filesystem. Also it enforces out of sourcetree builds for runs
and tests.
The one stop shop is probably now VSCode + the Code-D plugin, but I like to use Emacs.
projectile needs a new project definition to recognise dub projects. Mine looks like this:
(projectile-register-project-type
'dlang
'("dub.sdl")
:compile "~/bin/d build"
:test "~/bin/d test && ~/bin/d lint --errorFormat=digitalmars"
:run "~/bin/d run"
)
For a little tighter integration with emacs I use two flycheck checkers do build and test with coverage.
LSP is the new way to go, so I also use this with the builtin eglot (starting from emasc 29).
For code layout I use d run dfmt -- -i . without any special options. In the beginning e.g.
the angel brackets on a new line was very strange for me, but now I just go with dfmt's defaults hoping for
an uniform codebase also in other projects (actually I do not understand the need for customization in a
tool like dfmt). In long method call chains I use //dfmt off/on to fallback to manually
formatted sources.
Dlang already supports at least line coverage in its default tooling, so if you run your tests with
d test --coverage you get a bunch of nice *.lst files, that describe which lines
have been executed how often. Into the dub unittest configuration I like to add a
postRunCommands "$DUB run lst2errormessages || true" to get uncovered lines as warnings in the
normal "compiler" output.
d lint does the trick.
To keep best practices for my dlang projects in place, I have a small helper called ponies, that helps me to groom my projects.
Sooner or later licenses of dependencies are always getting interesting in real life projects. For that I use packageinfo in my dlang project to see, if there are some foul licenses involved (usually not in the dlang eco system).
Most official dlang development and dub packages are done on github and usethe excellent gitlab workflows (dlang-community/setup-dlang and codecov/codecov-action).
I wanted to try gitlab ci for a very long time and recently switched to that. All my dub projects now build with their own docker image, which is created by a shared git repo pulled in as submodule (at the moment in version v1.0.2). I am quite happy with this, besides that it takes quite a while to build a docker image and then wait on the individual steps of the workflow. A local build for a small project takes only a few seconds. The same "done right" on gitlab can easily take 5 minutes!