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.(corrections <setting>)controls whether the rule’s action may produce correction files that Dune reports as promotions. See Corrections for details. This field has been available since Dune 3.23.
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.
Corrections¶
Rules can opt in to correction discovery with the corrections field. This
is useful for custom tools that rewrite, format, lint, or otherwise suggest
updates to source files without using an explicit (diff? ...) action.
The field accepts the following settings:
ignoreis the default. Dune does not look for correction files produced by the rule.producemakes Dune run the action in a sandbox and, when the action finishes, scan the sandbox for files ending in.corrected. A file namedfoo.correctedis treated as the corrected version offoo. If the files differ, Dune prints a diff, fails the rule, and records a promotion fromfoo.correctedtofoo. The correction can then be applied withdune promoteordune runtest --auto-promote. If the corrected file is identical to the source file, no promotion is recorded and the rule succeeds.
For example:
(rule
(alias runtest)
(deps expected-output)
(corrections produce)
(action
(run ./check-and-rewrite.exe expected-output expected-output.corrected)))
The same naming convention applies in subdirectories: subdir/foo.corrected
is a correction for subdir/foo. Correction files that are themselves
dependencies of the rule are ignored, so copied dependencies are not promoted by
accident.
(corrections produce) cannot be combined with patch_back_source_tree
sandboxing.
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.