rule
----

The ``rule`` stanza is used to create custom user rules. It tells Dune how to
generate a specific set of files from a specific set of dependencies.

The syntax is as follows:

.. code:: dune

    (rule
     (action <action>)
     <optional-fields>)

``<action>`` is what you run to produce the targets from the dependencies. See
:doc:`/reference/actions/index` for more details.

``<optional-fields>`` are:

- ``(target <filename>)`` or ``(targets <filenames>)`` is a list of filenames
  (if defined with ``targets``) or exactly one filename (if defined with
  ``target``). Dune needs to statically know targets of each rule.
  ``(targets)`` can be omitted if it can be inferred from the action. See
  `inferred rules`_.

- ``(deps <deps-conf list>)`` specifies the dependencies of the rule. See
  :doc:`/concepts/dependency-spec` for more details.

- ``(mode <mode>)`` specifies how to handle the targets. See `modes`_ for
  details.

- ``(fallback)`` is deprecated and is the same as ``(mode fallback)``.

- ``(locks (<lock-names>))`` specifies that the action must be run while holding
  the following locks. See :doc:`/concepts/locks` for more details.

- ``(alias <alias-name>)`` specifies this rule's alias. Building this alias
  means building the targets of this rule.

- ``(aliases <alias-name list>)`` specifies many aliases for this rule.

- ``(package <package>)`` specifies this rule's package. This rule will be
  unavailable when installing other packages in release mode.

- ``(enabled_if <blang expression>)`` specifies the Boolean condition that must
  be true for the rule to be considered. The condition is specified using the
  :doc:`/reference/boolean-language`, and the field allows for
  :doc:`/concepts/variables` to appear in the expressions.

Please note: contrary to makefiles or other build systems, user rules currently
don't support patterns, such as a rule to produce ``%.y`` from ``%.x`` for any
given ``%``. This might be supported in the future.

.. _modes:

Modes
~~~~~

By default, a rule's target must not exist in the source tree because Dune will
error out when this is the case; however, it's possible to change this behavior
using the ``mode`` field. The following modes are available:

- ``standard`` - the standard mode.

- ``fallback`` - in this mode, when the targets are already present in the
  source tree, Dune will ignore the rule. It's an error if only a subset of the
  targets are present in the tree. Fallback rules are commonly used to generate
  default configuration files that may be generated by a configure script.

.. _promote:

- ``promote`` or ``(promote <options>)`` - in this mode, the files in the source
  tree will be ignored. Once the rule has been executed, the targets will be
  copied back to the source tree. The following options are available:

  - ``(until-clean)`` means that ``dune clean`` will remove the promoted files
    from the source tree.
  - ``(into <dir>)`` means that the files are promoted in ``<dir>`` instead of
    the current directory. This feature has been available since Dune 1.8.
  - ``(only <predicate>)`` means that only a subset of the targets should be
    promoted. The argument is similar to the argument of :doc:`subdir`,
    specified using the :doc:`/reference/predicate-language`.
    This feature has been available since Dune 1.10.

There are two use cases for ``promote`` rules. The first one is when the
generated code is easier to review than the generator, so it's easier to commit
the generated code and review it. The second is to cut down dependencies during
releases. By passing ``--ignore-promoted-rules`` to Dune, rules with ``(mode
promote)`` will be ignored, and the source files will be used instead. The
``-p/--for-release-of-packages`` flag implies ``--ignore-promote-rules``.
However, rules that promote only a subset of their targets via ``(only ...)``
are never ignored.

Inferred Rules
~~~~~~~~~~~~~~

When using the action DSL (see :doc:`/reference/actions/index`), the
dependencies and targets are usually obvious.

For instance:

.. code:: dune

    (rule
     (target b)
     (deps   a)
     (action (copy %{deps} %{target})))

In this example, the dependencies and targets are obvious by inspecting the
action. When this is the case, you can use the following shorter syntax and have
Dune infer dependencies and targets for you:

.. code:: dune

    (rule <action>)

For instance:

.. code:: dune

    (rule (copy a b))

Note that in Dune, targets must always be known statically. For instance, this
``(rule ...)`` stanza is rejected by Dune:

.. code:: dune

    (rule (copy a b.%{read:file}))

Directory targets
~~~~~~~~~~~~~~~~~

Note that at this time, Dune officially only supports user rules with targets in
the current directory. However, starting from Dune 3.0, we provide an
experimental support for *directory targets*, where an action can produce a
whole tree of build artifacts. To specify a directory target, you can use the
``(dir <dirname>)`` syntax. For example, the following stanza describes a rule
with a file target ``foo`` and a directory target ``bar``.

.. code:: dune

    (rule
     (targets foo (dir bar))
     (action  <action>))

To enable this experimental feature, add ``(using directory-targets 0.1)`` to
your ``dune-project`` file. However note that currently rules with a directory
target are always rebuilt. We are working on fixing this performance bug.
