rule¶
The rule stanza is used to create custom user rules. It tells Dune how to
generate files from dependencies, or how to run an action when an alias is
requested.
The syntax is as follows:
(rule
(action <action>)
<optional-fields>)
<action> is what you run to produce the targets from the dependencies, or
to build the attached aliases. See Actions for more
details.
A rule must either have at least one target or be attached to at least one
alias. Targets may be listed explicitly with target or targets, or
inferred from the action. Alias-only rules are useful for commands that don’t
produce files, such as benchmarks.
<optional-fields> are:
(target <filename>)or(targets <filenames>)is a list of filenames (if defined withtargets) or exactly one filename (if defined withtarget). Dune needs to statically know file targets of each rule.(targets)can be omitted if it can be inferred from the action. See inferred rules. It can also be omitted when the rule is only attached to an alias.(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. If the rule has file targets, building this alias builds those targets. If the rule has no file targets, building this alias runs the rule’s action.(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.
After a rule’s action exits, Dune records the produced targets. It must be able to read every target, including files inside directory targets. Dune also removes write permissions from generated files in the build directory before recording them. Actions may write their targets while they run, but generated targets should be treated as immutable once the rule finishes.
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.
promoteor(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 thatdune cleanwill 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. Starting from Dune 3.24, Dune supports 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>))
In Dune 3.0 through 3.23, directory targets require the experimental
(using directory-targets 0.1) extension.