.. _cross-compilation: ***************** Cross-Compilation ***************** .. TODO(diataxis) This can be turned into an how-to guide. Dune allows for cross-compilation by defining build contexts with multiple targets. Targets are specified by adding a ``targets`` field to the build context definition. ``targets`` takes a list of target name. It can be either: - ``native``, the native tools that can build binaries to run on the machine doing the build - the name of an alternative toolchain Note that at the moment, there is no official support for cross-compilation in OCaml. Dune supports the `opam-cross-` repositories from the `OCaml-cross organization on GitHub `_, such as: - `opam-cross-windows `_ - `opam-cross-android `_ - `opam-cross-ios `_ In particular: - to build Windows binaries using opam-cross-windows, write ``windows`` in the list of targets - to build Android binaries using opam-cross-android, write ``android`` in the list of targets - to build IOS binaries using opam-cross-ios, write ``ios`` in the list of targets For example, the following workspace file defines three different targets for the ``default`` build context: .. code:: dune (context (default (targets native windows android))) This configuration defines three build contexts: - ``default`` - ``default.windows`` - ``default.android`` Note that the ``native`` target is always implicitly added when not present; however, ``dune build @install`` will skip this context, i.e., ``default`` will only be used for building executables needed by the other contexts. With such a setup, calling ``dune build @install`` will build all the packages three times. Note that instead of writing a ``dune-workspace`` file, you can also use the ``-x`` command line option. Passing ``-x foo`` to ``dune`` without having a ``dune-workspace`` file is the same as writing the following ``dune-workspace`` file: .. code:: dune (context (default (targets foo))) If you have a ``dune-workspace`` and pass a ``-x foo`` option, ``foo`` will be added as target of all context stanzas. How Does it Work? ================= In such a setup, binaries that need to be built and executed in the ``default.windows`` or ``default.android`` contexts as part of the build will no longer be executed. Instead, all the binaries that will be executed come from the ``default`` context. One consequence of this is that all preprocessing (PPX or otherwise) will be done using binaries built in the ``default`` context. To clarify this with an example, let's assume that you have the following ``src/dune`` file: .. code:: dune (executable (name foo)) (rule (with-stdout-to blah (run ./foo.exe))) When building ``_build/default/src/blah``, dune will resolve ``./foo.exe`` to ``_build/default/src/foo.exe`` as expected. However, for ``_build/default.windows/src/blah`` dune will resolve ``./foo.exe`` to ``_build/default/src/foo.exe`` Assuming that the right packages are installed or that your workspace has no external dependencies, Dune will be able to cross-compile a given package without doing anything special. Some packages might still have to be updated to support cross-compilation. For instance if the ``foo.exe`` program in the previous example was using ``Sys.os_type``, it should instead take it as a command line argument: .. code:: dune (rule (with-stdout-to blah (run ./foo.exe -os-type %{os_type})))