I’m learning about cross-compilation in Dune. In dune-workspace a context stanza can have a targets field which lists the different findlib toolchains to build the project with, as well as a toolchain field which configures a findlib toolchain used to build the “native” target, implicitly (or explicitly) included in the targets list.
I’m trying to understand how these fields interact with the host field. The docs say:
(host <host_context>)chooses a different context to build binaries that are meant to be executed on the host machine, such as preprocessors.
If my project contains some development tools used elsewhere in the project, when cross-compiling the project the development tools need to be built to run on the build machine. It sounds like when building the project in some context foo, dev tools can be built in a specified “host” context bar, and the executables from bar will be run when building foo (since if foo uses a cross-compiling toolchain then its executables might not even be able to run on the build machine).
If that’s the case, I don’t understand why the host and targets fields can’t both appear in the same context stanza. For example I want to cross compile my project for windows but build dev tools natively in a separate context, so I wrote a dune-workspace like:
(lang dune 3.20)
(context
(default
(host local)
(targets windows)))
(context
(default
(name local)))
…but I get this error:
$ dune build
File "dune-workspace", lines 4-6, characters 1-45:
4 | (default
5 | (host local)
6 | (targets windows)))
Error: `targets` and `host` options cannot be used in the same context.
I’ll admit this example is contrived; I could just write:
(lang dune 3.20)
(context
(default
(targets windows)))
…and Dune will use tools from the implicit native target while building the windows target.
I can also use toolchain rather than targets to configure the cross-compiling toolchain, and that can be mixed with host:
(lang dune 3.20)
(context
(default
(host local)
(toolchain windows)))
(context
(default
(name local)))
But the fact that targets and host are mutually exclusive makes me feel like I don’t understand how host is supposed to be used.
Also while we’re at it, does anyone know why hosts can’t be daisy-chained? E.g.
(lang dune 3.20)
(context
(default
(host foo)))
(context
(default
(name foo)
(host bar)))
(context
(default
(name bar)))
It’s not particularly useful but I did this experiment to confirm my understanding of the host field, expecting Dune to build the project with the context bar, then use the tools built in bar to build the project in foo, and then use the tools in foo to build default, but instead I got this error:
$ dune build
File "dune-workspace", lines 8-10, characters 1-36:
8 | (default
9 | (name foo)
10 | (host bar)))
Error: Context 'foo' is both a host (for 'default') and a target (for 'bar').
I don’t understand this error because it says foo is a target for bar, but foo is a context, and thus far the term “target” has referred to toolchains which are separate from contexts. In Dune a target could also refer to a build target, however again I don’t see how to apply that concept to foo which is a build context.