3

I can think of at least a few use-cases or scenarios for this:

  • An "examples" configuration that builds multiple example programs.
  • A project with a client program and a host program.
  • A project with one main program and some associated utility programs (ex: gcc).

More generally, if the project has multiple output executables that have the same or similar set of dependencies, then it may make sense to build them all at once. It is easier for a user to decide which executable to run than to figure out how to make a DUB create the executable they want (they might not be a D developer that is familiar with DUB). It is convenient for me as a D developer too, because I can run fewer build commands to get what I want in total.

As an example, I might have a project layout like this:

dub.json
.gitignore
source/common/foo.d               (Code called by all examples)
source/examples/simple_example.d  (Build input with main function)
source/examples/complex_example.d (Build input with main function)
source/examples/clever_example.d  (Build input with main function)
bin/simple_example.exe            (Output executable)
bin/complex_example.exe           (Output executable)
bin/clever_example.exe            (Output executable)

Another project might look like this:

dub.json
.gitignore
source/common/netcode.d           (Code called by all programs)
source/common/logic.d             (Code called by all programs)
source/executables/host-daemon.d  (Does privileged things for the server)
source/executables/server.d       (Unprivileged network endpoint)
source/executables/client.d       (Queries the server)
bin/host-daemon                   (Output executable)
bin/server                        (Output executable)
bin/client                        (Output executable)

In either project, I would want to build all executables with a single invocation of DUB. Ideally, this would all be managed from one dub.json file, due to the interrelated nature of the inputs and outputs.

It seems like subPackages might be able to do this, but managing it from one dub.json file is "generally discouraged":

The sub directories /component1 and /component2 then contain normal packages and can be referred to as "mylib:component1" and "mylib:component2" from outside projects. To refer to sub packages within the same repository use the "*" version specifier.

It is also possible to define the sub packages within the root package file, but note that it is generally discouraged to put the source code of multiple sub packages into the same source folder. Doing so can lead to hidden dependencies to sub packages that haven't been explicitly stated in the "dependencies" section. These hidden dependencies can then result in build errors in conjunction with certain build modes or dependency trees that may be hard to understand.

Can DUB build multiple executables in one go, as above, and if so, what is the most recommended way and why?

chadjoan
  • 485
  • 3
  • 11

2 Answers2

3

I managed to do it using configurations, without subpackages.

First, you prefix all your main functions with versions specifiers.

Suppose you have 3 different files, each with its own main.

one.d:

....
versions(one)
void main() {
    ....
}

two.d:

....
versions(two)
void main() {
    ....
}

three.d:

....
versions(three)
void main() {
    ....
}

In your dub project file (I use sdl format here), you can define three configurations, such that each configuration defines a different version, and outputs to a different output file.

dub.sdl:

....
configuration "one" {
    versions "one"
    targetType "executable"
    targetName "one"
}

configuration "two" {
    versions "two"
    targetType "executable"
    targetName "two"
}

configuration "three" {
    versions "three"
    targetType "executable"
    targetName "three"
}

If you just call dub build, it will use the first configuration, but you can pass a different configuration:

dub build --config=two
hasen
  • 161,647
  • 65
  • 194
  • 231
0

"Subpackages are intended to modularize your package from the outside".

Instead, you should be able to create multiple configurations to do what you want like dub itself does (it defines multiple libraries but you could just as easily do multiple executables).

I'm not sure if there is a command to build all configurations at once. --combined maybe (the documentation isn't clear but I think it's actually for building all source files with a single compiler invocation rather that generating object files one by one).

eco
  • 2,219
  • 15
  • 20
  • Thank you for linking that forum post. It looks like I might become another subPackages abuser: configurations seem designed to manage the type of output and maybe optional dependencies (as in dub's json file); batch processing them for multiple outputs is not as trivial as I expect it to be. Interestingly, that D forum post linked DUB issue 1155, which had someone respond with "[...] What about the case when there're multiple examples?" I hope it isn't so, but maybe this is a use-case not considered. – chadjoan Jun 23 '17 at 23:59
  • Notably, when I tried to use configurations for this (as a stop-gap), it would fail because it tried to include all of the .d files in the examples subdirectory when compiling one of the example files (and give an error message about having multiple main functions). This was inspite of me trying `"excludedSourceFiles" : ["./source/examples/*"]` at all levels in the json file along with `"mainSourceFile" : "./source/examples/some_example.d"` in each configuration. As such, I wouldn't even be able to test the `--combined` suggestion :( – chadjoan Jun 24 '17 at 00:04