-
Notifications
You must be signed in to change notification settings - Fork 4k
/
make-variables.vm
493 lines (424 loc) · 17.9 KB
/
make-variables.vm
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
#if (!$singlePage)
<html devsite>
<head>
<meta name="project_path" value="/_project.yaml">
<meta name="book_path" value="/_book.yaml">
</head>
<body>
#end
#if (!$singlePage)
#parse("com/google/devtools/build/docgen/templates/be/header.vm")
#end
<!-- ============================================
variables
============================================
-->
<h1 class="page-title" id="make-variables">"Make" Variables</h1>
#if (!$singlePage)
<ul>
<li><a href="#use">Use</a></li>
<li><a href="#predefined_variables">Predefined variables</a></li>
<li><a href="#predefined_genrule_variables">Predefined genrule variables</a></li>
<li><a href="#predefined_label_variables">Predefined source/output path variables</a></li>
<li><a href="#custom_variables">Custom variables</a></li>
</ul>
#end
<p>
"Make" variables are a special class of expandable string variables available
to attributes marked as <i>"Subject to 'Make variable' substitution"</i>.
</p>
<p>
These can be used, for example, to inject specific toolchain paths into
user-constructed build actions.
</p>
<p>
Bazel provides both <i>predefined</i> variables, which are available to all
targets, and <i>custom</i> variables, which are defined in dependency targets
and only available to targets that depend on them.
</p>
<p>
The reason for the term "Make" is historical: the syntax and semantics of
these variables were originally intended to match <a
href="https://www.gnu.org/software/make/manual/html_node/Using-Variables.html">GNU
Make</a>.
</p>
<h2 id="use">Use</h2>
<p>
Attributes marked as <i>"Subject to 'Make variable' substitution"</i> can
reference the "Make" variable <code>FOO</code> as follows:
</p>
<p>
<code>my_attr = "prefix $(FOO) suffix"</code>
</p>
<p>
In other words, any substring matching <code>$(FOO)</code> gets expanded
to <code>FOO</code>'s value. If that value is <code>"bar"</code>, the final
string becomes:
</p>
<p>
<code>my_attr = "prefix bar suffix"</code>
</p>
<p>
If <code>FOO</code> doesn't correspond to a variable known to the consuming
target, Bazel fails with an error.
</p>
<p>
"Make" variables whose names are non-letter symbols, such as
<code>@</code>, can also be referenced using only a dollar sign, without
the parentheses. For example:
</p>
<p>
<code>my_attr = "prefix $@ suffix"</code>
</p>
<p>
To write <code>$</code> as a string literal (i.e. to prevent variable
expansion), write <code>$$</code>.
</p>
<h2 id="predefined_variables">Predefined variables</h2>
<p>
Predefined "Make" variables can be referenced by any attribute marked as
<i>"Subject to 'Make variable' substitution"</i> on any target.
</p>
<p>
To see the list of these variables and their values for a given set of build
options, run
</p>
<p><code>bazel info --show_make_env [build options]</code></p>
<p>
and look at the top output lines with capital letters.
</p>
<p><a href="https://github.com/bazelbuild/examples/tree/main/make-variables#predefined-variables">
See an example of predefined variables</a>.</p>
<p><strong>Toolchain option variables</strong></p>
<ul><!-- keep alphabetically sorted -->
<li><code>COMPILATION_MODE</code>:
<code>fastbuild</code>, <code>dbg</code>, or <code>opt</code>. (<a
href="https://bazel.build/docs/user-manual#flag--compilation_mode">more
details</a>)
</li>
</ul>
<p><strong>Path variables</strong></p>
<ul><!-- keep alphabetically sorted -->
<li>
<p>
<code>BINDIR</code>: The base of the generated binary tree for the target
architecture.
</p>
<p>
Note that a different tree may be used for programs that run during the
build on the host architecture, to support cross-compiling.
</p>
<p>
If you want to run a tool from within a <code>genrule</code>, the
recommended way to get its path is <code>$(<a
href="#predefined_label_variables">execpath</a> toolname)</code>,
where <i>toolname</i> must be listed in the <code>genrule</code>'s
<code><a
href="$expander.expandRef("genrule.tools")">tools</a></code> attribute.
</p>
</li>
<li><code>GENDIR</code>:
The base of the generated code tree for the target architecture.
</li>
</ul>
<p><strong>Machine architecture variables</strong></p>
<ul><!-- keep alphabetically sorted -->
<li> <code>TARGET_CPU</code>:
The target architecture's CPU, e.g. <code>k8</code>. </li>
</ul>
<h2 id="predefined_genrule_variables">Predefined genrule variables</h2>
<p>
The following are specially available to <code>genrule</code>'s
<code><a href="$expander.expandRef("genrule.cmd")">cmd</a></code> attribute and are
generally important for making that attribute work.
</p>
<p><a href="https://github.com/bazelbuild/examples/tree/main/make-variables#predefined-genrule-variables">
See an example of predefined genrule variables</a>.</p>
<ul><!-- keep alphabetically sorted -->
<li><code>OUTS</code>: The <code>genrule</code>'s <code><a
href="$expander.expandRef("genrule.outs")">outs</a></code> list. If you have
only one output file, you can also use <code>$@</code>.</li>
<li>
<code>SRCS</code>: The <code>genrule</code>'s <code><a
href="$expander.expandRef("genrule.srcs")">srcs</a></code> list (or more
precisely: the path names of the files corresponding to labels in the
<code><a href="$expander.expandRef("genrule.srcs")">srcs</a></code> list).
If you have only one source file, you can also use <code>$<</code>.
</li>
<li>
<code><</code>: <code>SRCS</code>, if it is a single file. Else triggers
a build error.
</li>
<li>
<code>@</code>: <code>OUTS</code>, if it is a single file. Else triggers a
build error.
</li>
<li>
<p>
<code>RULEDIR</code>: The output directory of the target, that is, the
directory corresponding to the name of the package containing the target
under the <code>genfiles</code> or <code>bin</code> tree. For
<code>//my/pkg:my_genrule</code> this always ends in <code>my/pkg</code>,
even if <code>//my/pkg:my_genrule</code>'s outputs are in subdirectories.
</p>
</li>
<li>
<p>
<code>@D</code>: The output directory. If
<a
href="$expander.expandRef("genrule.outs")">outs</a></code> has one entry,
this expands to the directory containing that file. If it has multiple
entries, this expands to the package's root directory in the
<code>genfiles</code> tree, <i>even if all output files are in the same
subdirectory</i>!
<!-- (as a consequence of the "middleman" implementation) -->
</p>
<p>
<b>Note:</b> Use <code>RULEDIR</code> over <code>@D</code> because
<code>RULEDIR</code> has simpler semantics and behaves the same way
regardless of the number of output files.
</p>
<p>
If the genrule needs to generate temporary intermediate files (perhaps as
a result of using some other tool like a compiler), it should attempt to
write them to <code>@D</code> (although <code>/tmp</code> will also
be writable) and remove them before finishing.
</p>
<p>
Especially avoid writing to directories containing inputs. They may be on
read-only filesystems. Even if not, doing so would trash the source tree.
</p>
</li>
</ul>
<h2 id="predefined_label_variables">Predefined source/output path variables</h2>
<p>
The predefined variables <code>execpath</code>, <code>execpaths</code>,
<code>rootpath</code>, <code>rootpaths</code>, <code>location</code>, and
<code>locations</code> take label parameters (e.g. <code>$(execpath
//foo:bar)</code>) and substitute the file paths denoted by that label.
</p>
<p>
For source files, this is the path relative to your workspace root.
For files that are outputs of rules, this is the file's <i>output path</i>
(see the explanation of <i>output files</i> below).
</p>
<p><a href="https://github.com/bazelbuild/examples/tree/main/make-variables#predefined-path-variables">
See an example of predefined path variables</a>.</p>
<ul>
<li>
<p>
<code>execpath</code>: Denotes the path beneath the
<a href="/docs/output_directories">execroot</a>
where Bazel runs build actions.
</p>
<p>
In the above example, Bazel runs all build actions in the directory linked
by the <code>bazel-myproject</code> symlink in your workspace root. The
source file <code>empty.source</code> is linked at the path
<code>bazel-myproject/testapp/empty.source</code>. So its exec path (which
is the subpath below the root) is <code>testapp/empty.source</code>. This
is the path build actions can use to find the file.
</p>
<p>
Output files are staged similarly, but are also prefixed with the subpath
<code>bazel-out/cpu-compilation_mode/bin</code> (or for the outputs of
tools: <code>bazel-out/cpu-opt-exec-hash/bin</code>). In the above example,
<code>//testapp:app</code> is a tool because it appears in
<code>show_app_output</code>'s <code><a
href="$expander.expandRef("genrule.tools")">tools</a></code> attribute.
So its output file <code>app</code> is written to
<code>bazel-myproject/bazel-out/cpu-opt-exec-hash/bin/testapp/app</code>.
The exec path is thus <code>
bazel-out/cpu-opt-exec-hash/bin/testapp/app</code>. This extra prefix
makes it possible to build the same target for, say, two different CPUs in
the same build without the results clobbering each other.
</p>
<p>
The label passed to this variable must represent exactly one file. For
labels representing source files, this is automatically true. For labels
representing rules, the rule must generate exactly one output. If this is
false or the label is malformed, the build fails with an error.
</p>
</li>
<li>
<p>
<code>rootpath</code>: Denotes the path that a built binary can use to
find a dependency at runtime relative to the subdirectory of its runfiles
directory corresponding to the main repository.
<strong>Note:</strong> This only works if <a
href="/reference/command-line-reference#flag--enable_runfiles">
<code>--enable_runfiles</code></a> is enabled, which is not the case on
Windows by default. Use <code>rlocationpath</code> instead for
cross-platform support.
<p>
This is similar to <code>execpath</code> but strips the configuration
prefixes described above. In the example from above this means both
<code>empty.source</code> and <code>app</code> use pure workspace-relative
paths: <code>testapp/empty.source</code> and <code>testapp/app</code>.
</p>
<p>
This has the same "one output only" requirements as <code>execpath</code>.
</p>
</li>
<li>
<p>
<code>rlocationpath</code>: The path a built binary can pass to the <code>
Rlocation</code> function of a runfiles library to find a dependency at
runtime, either in the runfiles directory (if available) or using the
runfiles manifest.
</p>
<p>
This is similar to <code>rootpath</code> in that it does not contain
configuration prefixes, but differs in that it always starts with the
name of the repository. In the example from above this means that <code>
empty.source</code> and <code>app</code> result in the following
paths: <code>myproject/testapp/empty.source</code> and <code>
myproject/testapp/app</code>.
</p>
<p>
Passing this path to a binary and resolving it to a file system path using
the runfiles libraries is the preferred approach to find dependencies at
runtime. Compared to <code>rootpath</code>, it has the advantage that it
works on all platforms and even if the runfiles directory should not be
available.
</p>
<p>
This has the same "one output only" requirements as <code>execpath</code>.
</p>
</li>
<li>
<code>location</code>: A synonym for either <code>execpath</code> or
<code>rootpath</code>, depending on the attribute being expanded. This is
legacy pre-Starlark behavior and not recommended unless you really know what
it does for a particular rule. See <a
href="https://github.com/bazelbuild/bazel/issues/2475#issuecomment-339318016">#2475</a>
for details.
</li>
</ul>
<p>
<code>execpaths</code>, <code>rootpaths</code>, <code>rlocationpaths</code>,
and <code>locations</code> are the plural variations of <code>execpath</code>,
<code>rootpath</code>, <code>rlocationpaths</code>, and<code>location</code>,
respectively. They support labels producing multiple outputs, in which case
each output is listed separated by a space. Zero-output rules and malformed
labels produce build errors.
</p>
<p>
All referenced labels must appear in the consuming target's <code>srcs</code>,
output files, or <code>deps</code>. Otherwise the build fails. C++ targets can
also reference labels in <code><a
href="$expander.expandRef("cc_binary.data")">data</a></code>.
</p>
<p>
Labels don't have to be in canonical form: <code>foo</code>, <code>:foo</code>
and <code>//somepkg:foo</code> are all fine.
</p>
<h2 id="custom_variables">Custom variables</h2>
<p>
Custom "Make" variables can be referenced by any attribute marked as
<i>"Subject to 'Make variable' substitution"</i>, but only on targets that
depend on other targets that <i>define</i> these variables.
</p>
<p>
As best practice all variables should be custom unless there's a really good
reason to bake them into core Bazel. This saves Bazel from having to load
potentially expensive dependencies to supply variables consuming tarets may
not care about.
</p>
<p><strong>C++ toolchain variables</strong></p>
<p>
The following are defined in C++ toolchain rules and available to any rule
that sets <code>toolchains =
["@bazel_tools//tools/cpp:current_cc_toolchain"]</code> (or
<code>"@bazel_tools//tools/cpp:current_cc_host_toolchain"</code>
for the host toolchain equivalent). Some rules, like <code><a
href="$expander.expandRef("java_binary")">java_binary</a></code>, implicitly
include the C++ toolchain in their rule definition. They inherit these variables
automatically.
</p>
<p>
The built-in C++ rules are much more sophisticated than "run the compiler on
it". In order to support compilation modes as diverse as *SAN, ThinLTO,
with/without modules, and carefully optimized binaries at the same time as
fast running tests on multiple platforms, the built-in rules go to great
lengths to ensure the correct inputs, outputs, and command-line flags are set
on each of potentially multiple internally generated actions.
</p>
<p>
These variables are a fallback mechanism to be used by language experts in
rare cases. If you are tempted to use them, please <a
href="https://bazel.build/support.html">contact the Bazel devs</a> first.
</p>
<ul><!-- keep alphabetically sorted -->
<li><code>ABI</code>: The C++ ABI version. </li>
<li> <code>AR</code>: The "ar" command from crosstool. </li>
<li class="harmful"> <code>C_COMPILER</code>:
The C/C++ compiler identifier, e.g. <code>llvm</code>.
</li>
<li class="harmful">
<p><code>CC</code>: The C and C++ compiler command.</p>
<p>
We strongly recommended always using <code>CC_FLAGS</code> in
combination with <code>CC</code>. Fail to do so at your own risk.
</p>
</li>
<li class="harmful"><code>CC_FLAGS</code>: A minimal set of flags for the C/C++
compiler to be usable by genrules. In particular, this contains flags to
select the correct architecture if <code>CC</code> supports multiple
architectures.
</li>
<li> <code>NM</code>: The "nm" command from crosstool. </li>
<li> <code>OBJCOPY</code>: The objcopy command from the same suite as the C/C++
compiler. </li>
<li> <code>STRIP</code>: The strip command from the same suite as the C/C++
compiler.</li>
</ul>
<p><strong>Java toolchain variables</strong></p>
<p>
The following are defined in Java toolchain rules and available to any rule
that sets <code>toolchains =
["@bazel_tools//tools/jdk:current_java_runtime"]</code> (or
<code>"@bazel_tools//tools/jdk:current_host_java_runtime"</code>
for the host toolchain equivalent).
</p>
<p>
Most of the tools in the JDK should not be used directly. The built-in Java
rules use much more sophisticated approaches to Java compilation and packaging
than upstream tools can express, such as interface Jars, header interface
Jars, and highly optimized Jar packaging and merging implementations.
</p>
<p>
These variables are a fallback mechanism to be used by language experts in
rare cases. If you are tempted to use them, please <a
href="https://bazel.build/support.html">contact the Bazel devs</a> first.
</p>
<ul><!-- keep alphabetically sorted -->
<li class="harmful"> <code>JAVA</code>: The "java" command (a Java virtual
machine). Avoid this, and use a <code><a
href="$expander.expandRef("java_binary")">java_binary</a></code> rule
instead where possible. May be a relative path. If you must change
directories before invoking <code>java</code>, you need to capture the
working directory before changing it.
</li>
<li class="harmful"><code>JAVABASE</code>: The base directory containing the
Java utilities. May be a relative path. It will have a "bin"
subdirectory.
</li>
</ul>
<p><strong>Starlark-defined variables</strong></p>
<p>
Rule and <a href="$expander.expandRef("toolchains")">toolchain</a> writers can define
completely custom variables by returning a
<a href="/rules/lib/TemplateVariableInfo">TemplateVariableInfo</a>
provider. Any rules depending on these through the
<code>toolchains</code> attribute can then read their values:
</p>
<p><a href="https://github.com/bazelbuild/examples/tree/main/make-variables#custom-starlark-defined-variables">
See an example of Starlark-defined variables</a>.</p>
#if (!$singlePage)
#parse("com/google/devtools/build/docgen/templates/be/footer.vm")
#end
#if (!$singlePage)
</body>
</html>
#end