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:

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

<action> is what you run to produce the targets from the dependencies. See Actions for more details.

<optional-fields> are:

  • (target <filename>) or (targets <filenames>) ``<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 Dependency Specification 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 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 Boolean Language, and the field allows for 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

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 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 subdir, specified using the 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 Actions), the dependencies and targets are usually obvious.

For instance:

(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:

(rule <action>)

For instance:

(rule (copy a b))

Note that in Dune, targets must always be known statically. For instance, this (rule ...) stanza is rejected by 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.

(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.