This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
266
unikernel/duniverse/dune_/doc/faq.rst
Normal file
266
unikernel/duniverse/dune_/doc/faq.rst
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
***
|
||||
FAQ
|
||||
***
|
||||
|
||||
.. TODO(diataxis)
|
||||
|
||||
This is an odd one - most of these questions are not frequently asked at all.
|
||||
|
||||
Some of these are mini how-to guides, or sections of existing guides.
|
||||
|
||||
Why do many Dune projects contain a ``Makefile``?
|
||||
=================================================
|
||||
|
||||
Many Dune projects contain a root ``Makefile``. It's often only there for
|
||||
convenience for the following reasons:
|
||||
|
||||
1. There are many different build systems out there, all with a different CLI.
|
||||
If you have been hacking for a long time, the one true invocation you know
|
||||
is ``make && make install``, possibly preceded by ``./configure``.
|
||||
|
||||
2. You often have a few common operations that aren't part of the build, so
|
||||
``make <blah>`` is a good way to provide them.
|
||||
|
||||
3. ``make`` is shorter to type than ``dune build @install``
|
||||
|
||||
How to add a configure step to a Dune project?
|
||||
==============================================
|
||||
|
||||
The with-configure-step_ example shows one way to add a configure step that
|
||||
preserves composability; i.e., it doesn't require manually running the
|
||||
``./configure`` script when working on multiple projects simultaneously.
|
||||
|
||||
.. _with-configure-step: https://github.com/ocaml/dune/tree/master/example/with-configure-step.t
|
||||
|
||||
Can I use ``topkg`` with Dune?
|
||||
==============================
|
||||
|
||||
While it's possible to use the topkg-jbuilder_, it's not recommended.
|
||||
dune-release_ subsumes ``topkg-jbuilder`` and is specifically tailored to Dune
|
||||
projects.
|
||||
|
||||
|
||||
How do I publish my packages with Dune?
|
||||
=======================================
|
||||
|
||||
Dune is just a build system and considers publishing outside of its scope.
|
||||
However, the dune-release_ project is specifically designed for releasing Dune
|
||||
projects to opam. We recommend using this tool for publishing Dune packages.
|
||||
|
||||
Where can I find some examples of projects using Dune?
|
||||
======================================================
|
||||
|
||||
The dune-universe_ repository contains a snapshot of the latest versions of all
|
||||
opam packages that depend on Dune. Therefore, it's a useful reference to find
|
||||
different approaches for constructing build rules.
|
||||
|
||||
What is Jenga?
|
||||
==============
|
||||
|
||||
jenga_ is a build system developed by Jane Street, mainly for internal use. It
|
||||
was never usable outside of Jane Street, so it's not recommended for general
|
||||
use. It has no relationship to Dune apart from Dune being the successor to
|
||||
Jenga externally. Eventually, Dune is expected to replace Jenga internally at
|
||||
Jane Street as well.
|
||||
|
||||
.. _dune-universe: https://github.com/dune-universe/dune-universe
|
||||
.. _topkg-jbuilder: https://github.com/samoht/topkg-jbuilder
|
||||
.. _dune-release: https://github.com/samoht/dune-release
|
||||
.. _jenga: https://github.com/janestreet/jenga
|
||||
|
||||
How to make warnings non-fatal?
|
||||
===============================
|
||||
|
||||
`jbuilder` formerly displayed warnings, but most of them wouldn't stop the
|
||||
build. However, Dune makes all warnings fatal by default. This can be a
|
||||
challenge when porting a codebase to Dune. There are two ways to make warnings
|
||||
non-fatal:
|
||||
|
||||
- The ``jbuilder`` compatibility executable works even with ``dune`` files. You
|
||||
can use it while some warnings remain and then switch over to the ``dune``
|
||||
executable. This is the recommended way to handle the situation.
|
||||
- You can pass ``--profile release`` to ``dune``. It will set up different
|
||||
compilation options that usually make sense for release builds, including
|
||||
making warnings non-fatal. This is done by default when installing packages
|
||||
from opam.
|
||||
- You can change the flags used by the ``dev`` profile by adding the following
|
||||
stanza to a ``dune`` file:
|
||||
|
||||
.. code:: dune
|
||||
|
||||
(env
|
||||
(dev
|
||||
(flags (:standard -warn-error -A))))
|
||||
|
||||
How to turn specific errors into warnings?
|
||||
==========================================
|
||||
|
||||
Dune is strict about warnings by default in that all warnings are treated as
|
||||
fatal errors. To change certain errors into warnings for a project, you can add
|
||||
the following to ``dune-workspace``:
|
||||
|
||||
.. code:: dune
|
||||
|
||||
(env (dev (flags :standard -warn-error -27-32)))
|
||||
|
||||
In this example, the warnings 27 (unused-var-strict) and 32
|
||||
(unused-value-declaration) are treated as warnings rather than errors.
|
||||
|
||||
How to display the output of commands as they run?
|
||||
==================================================
|
||||
|
||||
When Dune runs external commands, it redirects and saves their output, then
|
||||
displays it when complete. This ensures that there's no interleaving when
|
||||
writing to the console.
|
||||
|
||||
But this might not be what the you want. For example, when you debug a hanging
|
||||
build.
|
||||
|
||||
In that case, one can pass ``-j1 --no-buffer`` so the commands are directly
|
||||
printed on the console (and the parallelism is disabled so the output stays
|
||||
readable).
|
||||
|
||||
How can I generate an ``mli`` file from an ``ml`` file?
|
||||
=======================================================
|
||||
|
||||
When a module starts as just an implementation (``.ml`` file), it can be
|
||||
tedious to define the corresponding interface (``.mli`` file).
|
||||
|
||||
It is possible to use the ``ocaml-print-intf`` program (available on opam
|
||||
through ``$ opam install ocaml-print-intf``) to generate the right ``mli``
|
||||
file:
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ dune exec -- ocaml-print-intf ocaml_print_intf.ml
|
||||
val root_from_verbose_output : string list -> string
|
||||
val target_from_verbose_output : string list -> string
|
||||
val build_cmi : string -> string
|
||||
val print_intf : string -> unit
|
||||
val version : unit -> string
|
||||
val usage : unit -> unit
|
||||
|
||||
The ``ocaml-print-intf`` program has special support for Dune, so it will
|
||||
automatically understand external dependencies.
|
||||
|
||||
How can I build a single library?
|
||||
=================================
|
||||
|
||||
You might want to do this when you don't have all the dependencies installed to
|
||||
compile an entire project, or parts of the project don't build for whatever
|
||||
reason. Maybe you want to check if your changes compile or produce build
|
||||
artifacts needed by ``ocaml-lsp-server``.
|
||||
|
||||
Suppose you have a library defined in ``src/foo/dune``:
|
||||
|
||||
.. code:: dune
|
||||
|
||||
(library
|
||||
(public_name my_library)
|
||||
...)
|
||||
|
||||
You can build this library on its own by running the following from the project
|
||||
root directory:
|
||||
|
||||
.. code:: console
|
||||
|
||||
$ dune build %{cmxa:src/foo/my_library}
|
||||
|
||||
Note that the path (``src/foo`` in the example above) is relative to the current
|
||||
directory - not the project root. If the library defines a ``name`` distinct from
|
||||
its ``public_name`` then that can be used interchangeably with the ``public_name``
|
||||
in this command.
|
||||
|
||||
Why does ``source_tree`` ignore files and directories when they begin with a "." (period)?
|
||||
==========================================================================================
|
||||
|
||||
Dune's default behaviour is to ignore files and directories starting with "."
|
||||
when copying directories with ``source_tree``. This is to avoid accidentally
|
||||
copying the ``.git`` directory into the ``_build`` directory during a build.
|
||||
|
||||
This is a common source of confusion when interoperating with other libraries
|
||||
that use hidden directories for configuration, such as Rust. For example
|
||||
consider this rule which builds a Rust library contained in a subdirectory
|
||||
foo-rs:
|
||||
|
||||
.. code:: dune
|
||||
|
||||
(rule
|
||||
(target foo.a)
|
||||
(deps
|
||||
(source_tree foo-rs))
|
||||
(action
|
||||
(progn
|
||||
(chdir
|
||||
foo-rs
|
||||
(run cargo build --release))
|
||||
(run mv foo-rs/target/release/%{target} %{target}))))
|
||||
|
||||
The build config for the Rust project will be in a directory
|
||||
``foo-rs/.cargo/config.toml``, and by default the ``.cargo`` directory won't
|
||||
get copied into the ``_build`` directory and so the Rust project will build
|
||||
with an incorrect configuration.
|
||||
|
||||
To fix this, create a ``dune`` file at the top level of the Rust project (i.e.,
|
||||
``foo-rs/dune``):
|
||||
|
||||
.. code:: dune
|
||||
|
||||
(dirs :standard .cargo)
|
||||
|
||||
If you're following the standard advice for embedding Rust projects into Dune
|
||||
projects then you likely already have a ``dune`` project inside your Rust
|
||||
project that looks like:
|
||||
|
||||
.. code:: dune
|
||||
|
||||
(dirs :standard \ target)
|
||||
(data_only_dirs vendor)
|
||||
|
||||
In this case you can update it to look like this:
|
||||
|
||||
.. code:: dune
|
||||
|
||||
(dirs :standard .cargo \ target)
|
||||
(data_only_dirs vendor)
|
||||
|
||||
Why can't I write inline tests in a package without users needing to install ``ppx_inline_test``?
|
||||
=================================================================================================
|
||||
|
||||
If you came to OCaml from Rust and noticed that Dune has a feature for running
|
||||
inline tests you might be wondering how to do the OCaml equivalent of:
|
||||
|
||||
.. code:: rust
|
||||
|
||||
// define a private function
|
||||
fn foo() { ... }
|
||||
|
||||
// test the function right next to its definition
|
||||
#[test]
|
||||
fn test_of_foo() { ... }
|
||||
|
||||
That is, writing tests for private functions right next to the definition of
|
||||
those functions. The :ref:`inline_tests` documentation describes how to do this
|
||||
using the ``ppx_inline_test`` package; however, if you do this in your package,
|
||||
then your package must `unconditionally` depend on the ``ppx_inline_test``
|
||||
package. Opam has a notion of test-only dependencies (its ``with-test`` flag),
|
||||
but you cannot use this with ``ppx_inline_test``. The consequence of this is
|
||||
that anyone depending on your package is also transitively depending on
|
||||
``ppx_inline_test`` as well as all of its dependencies.
|
||||
|
||||
The reason for this is OCaml code with preprocessor directives (such as those
|
||||
used for inline tests with ``ppx_inline_test``) is technically not valid OCaml
|
||||
code until it has been preprocessed. Unlike the cargo build system used for
|
||||
Rust, Dune does not have a preprocessor built into it. Instead, it relies on
|
||||
external tools (such as ``ppx_inline_test``) to parse the code and replace any
|
||||
preprocessor directives with valid OCaml. Dune doesn't know how to parse OCaml
|
||||
code at all so it can't even remove inline tests from the code in cases where
|
||||
``ppx_inline_test`` is unavailable.
|
||||
|
||||
The blessed workaround for folks who want to use ``ppx_inline_test`` in their
|
||||
packages but don't want to add it as a dependency is to create a new
|
||||
(unreleased) package which contains all the tests. In the original package,
|
||||
expose all the private APIs you intend to test via public modules named
|
||||
something foreboding such as ``For_test`` so your users know not to rely on
|
||||
their contents and then have the test package define tests that call your
|
||||
"private" APIs through the ``For_test`` modules.
|
||||
Loading…
Add table
Add a link
Reference in a new issue