summaryrefslogtreecommitdiff
path: root/doc/concepts/built-in-rules.md
blob: 319d0d82cf6387e34681455a4c429b63288a1087 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
Built-in rules
==============

Targets are defined in `TARGETS` files. Each target file is a single
`JSON` object. If the target name is contained as a key in that object,
the corresponding value defines the target; otherwise it is implicitly
considered a source file. The target definition itself is a `JSON`
object as well. The mandatory key `"type"` specifies the rule defining
the target; the meaning of the remaining keys depends on the rule
defining the target.

There are a couple of rules built in, all named by a single string. The
user can define additional rules (and, in fact, we expect the majority
of targets to be defined by user-defined rules); referring to them in a
qualified way (with module) will always refer to those even if new
built-in rules are added later (as built-in rules will always be only
named by a single string).

The following rules are built in. Built-in rules can have a special
syntax.

`"export"`
----------

The `"export"` rule evaluates a given target in a specified
configuration. More precisely, the field `"target"` has to name a single
target (not a list of targets), the field `"flexible_config"` a list of
strings, treated as variable names, and the field `"fixed_config"` has
to be a map that is taken unevaluated. It is a requirement that the
domain of the `"fixed_config"` and the `"flexible_config"` be disjoint.
The optional fields `"doc"` and `"config_doc"` can be used to describe
the target and the `"flexible_config"`, respectively.

To evaluate an `"export"` target, first the configuration is restricted
to the `"flexible_config"` and then the union with the `"fixed_config"`
is built. The target specified in `"target"` is then evaluated. It is a
requirement that this target be untainted. The result is the result of
this evaluation; artifacts, runfiles, and provides map are forwarded
unchanged.

The main point of the `"export"` rule is, that the relevant part of the
configuration can be determined without having to analyze the target
itself. This makes such rules eligible for target-level caching
(provided the content of the repository as well as all reachable ones
can be determined cheaply). This eligibility is also the reason why it
is good practice to only depend on `"export"` targets of other
repositories.

`"install"`
-----------

The `"install"` rules allows to stage artifacts (and runfiles) of other
targets in a different way. More precisely, a new stage (i.e., map of
artifacts with keys treated as file names) is constructed in the
following way.

The runfiles from all targets in the `"deps"` field are taken; the
`"deps"` field is an evaluated field and has to evaluate to a list of
targets. It is an error, if those runfiles conflict.

The `"files"` argument is a special form. It has to be a map, and the
keys are taken as paths. The values are evaluated and have to evaluate
to a single target. That target has to have a single artifact or no
artifacts and a single run file. In this way, `"files"` defines a stage;
this stage overlays the runfiles of the `"deps"` and conflicts are
ignored.

Finally, the `"dirs"` argument has to evaluate to a list of pairs (i.e.,
lists of length two) with the first argument a target name and the
second argument a string, taken as directory name. For each entry, both,
runfiles and artifacts of the specified target are staged to the
specified directory. It is an error if a conflict with the stage
constructed so far occurs.

Both, runfiles and artifacts of the `"install"` target are the stage
just described. An `"install"` target always has an empty provides map.
Any provided information of the dependencies is discarded.

`"generic"`
-----------

The `"generic"` rules allows to define artifacts as the output of an
action. This is mainly useful for ad-hoc constructions; for anything
occurring more often, a proper user-defined rule is usually the better
choice.

The `"deps"` argument is evaluated and has to evaluate to a list of
target names. The runfiles and artifacts of these targets form the
inputs of the action. Conflicts are not an error and resolved by giving
precedence to the artifacts over the runfiles; conflicts within
artifacts or runfiles are resolved in a latest-wins fashion using the
order of the targets in the evaluated `"deps"` argument.

The fields `"cmds"`, `"out_dirs"`, `"outs"`, and `"env"` are evaluated
fields where `"cmds"`, `"out_dirs"`, and `"outs"` have to evaluate to a
list of strings, and `"env"` has to evaluate to a map of strings. During
their evaluation, the functions `"outs"` and `"runfiles"`
can be used to access the logical paths of the artifacts
and runfiles, respectively, of a target specified in `"deps"`. Here,
`"env"` specifies the environment in which the action is carried out.
`"out_dirs"` and `"outs"` define the output directories and files,
respectively, the action has to produce. Since some artifacts are to be
produced, at least one of `"out_dirs"` or `"outs"` must be a non-empty
list of strings. It is an error if one or more paths are present in both
the `"out_dirs"` and `"outs"`. Finally, the strings in `"cmds"` are
extended by a newline character and joined, and command of the action is
interpreting this string by `sh`.

The artifacts of this target are the outputs (as declared by
`"out_dirs"` and `"outs"`) of this action. Runfiles and provider map are
empty.

`"file_gen"`
------------

The `"file_gen"` rule allows to specify a file with a given content. To
be able to accurately report about file names of artifacts or runfiles
of other targets, they can be specified in the field `"deps"` which has
to evaluate to a list of targets. The names of the artifacts and
runfiles of a target specified in `"deps"` can be accessed through the
functions `"outs"` and `"runfiles"`, respectively, during the evaluation
of the arguments `"name"` and `"data"` which have to evaluate to a
single string.

Artifacts and runfiles of a `"file_gen"` target are a singleton map with
key the result of evaluating `"name"` and value a (non-executable) file
with content the result of evaluating `"data"`. The provides map is
empty.

`"tree"`
--------

The `"tree"` rule allows to specify a tree out of the artifact stage of
given targets. More precisely, the deps field `"deps"` has to evaluate
to a list of targets. For each target, runfiles and artifacts are
overlayed in an artifacts-win fashion and the union of the resulting
stages is taken; it is an error if conflicts arise in this way. The
resulting stage is transformed into a tree. Both, artifacts and runfiles
of the `"tree"` target are a singleton map with the key the result of
evaluating `"name"` (which has to evaluate to a single string) and value
that tree.

`"configure"`
-------------

The `"configure"` rule allows to configure a target with a given
configuration. The field `"target"` is evaluated and the result of the
evaluation must name a single target (not a list). The `"config"` field
is evaluated and must result in a map, which is used as configuration
for the given target.

This rule uses the given configuration to overlay the current
environment for evaluating the given target, and thereby performs a
configuration transition. It forwards all results
(artifacts/runfiles/provides map) of the configured target to the upper
context. The result of a target that uses this rule is the result of the
target given in the `"target"` field (the configured target).

As a full configuration transition is performed, the same care has to be
taken when using this rule as when writing a configuration transition in
a rule. Typically, this rule is used only at a top-level target of a
project and configures only variables internally to the project. In any
case, when using non-internal targets as dependencies (i.e., targets
that a caller of the `"configure"` potentially might use as well), care
should be taken that those are only used in the initial configuration.
Such preservation of the configuration is necessary to avoid conflicts,
if the targets depended upon are visible in the `"configure"` target
itself, e.g., as link dependency (which almost always happens when
depending on a library). Even if a non-internal target depended upon is
not visible in the `"configure"` target itself, requesting it in a
modified configuration causes additional overhead by increasing the
target graph and potentially the action graph.