Back to Bazel

Make Variables

docs/versions/7.5.0/reference/be/make-variables.mdx

9.1.018.6 KB
Original Source
<html devsite> <head> <meta name="project_path" value="/_project.yaml"> <meta name="book_path" value="/versions/7.5.0/_book.yaml"> </head> <body> <!-- This document is synchronized with Bazel releases. To edit, submit changes to the Bazel source code. --> <!-- Generated by //src/main/java/com/google/devtools/build/docgen:build-encyclopedia.zip --> <!-- ============================================ variables ============================================ --> <h1 class="page-title" id="make-variables">Make Variables</h1>

{% dynamic setvar source_file "src/main/java/com/google/devtools/build/docgen/templates/be/make-variables.vm" %} {% dynamic setvar version "7.5.0" %} {% dynamic setvar original_path "/reference/be/make-variables" %} {% include "_buttons.html" %}

<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> <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/versions/7.5.0/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="/versions/7.5.0/reference/be/general.html#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="/versions/7.5.0/reference/be/general.html#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="/versions/7.5.0/reference/be/general.html#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="/versions/7.5.0/reference/be/general.html#genrule.srcs">srcs</a></code> list (or more precisely: the path names of the files corresponding to labels in the <code><a href="/versions/7.5.0/reference/be/general.html#genrule.srcs">srcs</a></code> list). If you have only one source file, you can also use <code>$&lt;</code>. </li> <li> <code>&lt;</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="/versions/7.5.0/reference/be/general.html#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="/versions/7.5.0/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="/versions/7.5.0/reference/be/general.html#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="/versions/7.5.0/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> The <code>rootpath</code> of a file in an external repository <code>repo</code> will start with <code>../repo/</code>, followed by the repository-relative path. </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> The <code>rlocationpath</code> of a file in an external repository <code>repo</code> will start with <code>repo/</code>, followed by the repository-relative path. </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 is not 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="/versions/7.5.0/reference/be/c-cpp.html#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> Some rules, like <code><a href="/versions/7.5.0/reference/be/java.html#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/versions/7.5.0/help">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/versions/7.5.0/help">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="/versions/7.5.0/reference/be/java.html#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="/versions/7.5.0/docs/toolchains">toolchain</a> writers can define completely custom variables by returning a <a href="/versions/7.5.0/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> <!-- Generated footer --> </body> </html>