Buck: String Parameter Macros

String Parameter Macros

This is liable to change in the future.

Some rules allow the use of specialized macros embedded within the strings of their parameters. These string parameter macros provide additional functionality, such as exposing the output paths of other rules.

Rules that support string parameter macros are:

Note that cxx_genrule supports only the $(exe ...) and $(location ...) macros.

Format

String parameter macros have the form

$([@]macroname [ argument ... ])

String parameter macros take a space-separated list of arguments, where each argument is a build target pattern.

Note that the $(query_* ...) macros require a fully-qualified build target and do not support build target patterns.

How to manage long expanded values

In some cases, the results of the expanded macro might be so long that they exceed a limit in your operating environment. For example, if you use the results of an expanded macro in Bash, it could exceed Bash's command-line limits.

To work around these limits, prefix the macro name with the @ character. Buck then writes the results of the expanded macro to a temporary file and replaces the macro with the path to that file while keeping the @ prefix. For example

$(@query_targets_and_outputs //...)

expands to something similar to

@/tmp/tempfile

Many applications recognize the @ prefix to mean: read the contents of this file to obtain the necessary arguments.

How to prevent expansion

If you need to prevent expansion of a string parameter macro, prefix the macro with a backslash.

\$(dirname ...)

For an example of preventing expansion in the context of a rule, see the Examples section below.

Supported macros

  • $(classpath //:foo) expands to the set of JARs that are in the classpath of the given target.
  • $(classpath_abi //:foo) expands to the set of Application Binary Interface (ABI) JARs that are in the classpath of the given target. For more information about using ABI JARs with Buck, see the topic Java ABIs.
  • $(exe //:foo) expands to the executable output of the given target—if the target produces such an executable.
  • $(location //:foo) expands to the output file or directory of the given target.
  • $(location //:foo[output]) expands to the named output file or directory of the given target, for rules that expose supplementary outputs.
  • $(maven_coords //:foo) expands to the maven coordinates associated with the given target.
  • $(output name) expands to the path of the named output of the rule in which you use this macro. Used only for rules that allow named supplementary outputs.
  • $(query_targets "queryfunction(//:foo)") executes the given query and expands to the list of targets that match. See the Query functions section below for the list of supported queryfunctions.
  • $(query_outputs "queryfunction(//:foo)") executes the given query and expands to the output files of the targets that match. See the Query functions section below for the list of supported queryfunctions.
  • $(query_targets_and_outputs [SEPARATOR] "queryfunction(//:foo)") executes the given query and expands to both the target names and the output files of the targets that match. Targets and paths are separated by SEPARATOR if provided, or a space if it is not. See the Query functions section below for the list of supported queryfunctions.

Query functions

The query_* macros accept a quoted query expression which supports the following query functions.

All of these except for classpath behave the same as the corresponding operations in buck query.

The classpath query function is used to query the classpath of java_library rules. It takes an optional second argument to limit the depth of the traversal. Its behavior is similar to the corresponding operation in buck audit.

The items in the preceding list link to the corresponding descriptions in the buck query and buck audit topics.

Examples

Example: Use a string parameter macro in a genrule() to copy the output of another rule.

genrule(
  name = 'gen',
  out  = 'out.txt',
  cmd  = 'cp $(location //some/other:rule) $OUT',
)

Example: Use a backslash to prevent macro expansion. The rule passes the dirname command to the shell to execute in a subshell; dirname is a Unix/Linux command-line utility that returns the directory of a specified file. We need to use an escape because the syntax for subshells is the same as the syntax for string parameter macros.

genrule(
  name = 'gen',
  out  = 'out.txt',
  cmd  = 'cp $SRCS \$(dirname $OUT)',
  srcs = [
    'test1.txt',
    'test2.txt',
  ],
)

Example: Query macro

The following example adds an apk_genrule to the BUCK file that is used in the cross-platform Buck sample from GitHub. The genrule, string_param, writes the transitive closure of dependencies for the android_binary rule, demo-app, to the file deps.txt.

android_binary(
  name = 'demo-app',
  manifest = 'AndroidManifest.xml',
  keystore = '//android/keystores:debug',
  deps = [
    '//android/java/com/facebook/buck/demo:lib',
  ],
)

apk_genrule(
  name = 'string_param',
  apk  = ':demo-app',
  srcs = [ '//android/java/com/facebook/buck/demo:lib' ],
  cmd = 'mkdir $OUT; echo deps: $(query_targets deps(//android:demo-app)) > $OUT/deps.txt',
  out = 'out-dir'
)

Frequently Asked Questions (FAQ)

  • When are macros evaluated? Macros are evaluated before the command is passed to the shell for execution. You can think of them as simple string replacements.
  • Can macros be nested? Macros cannot be nested. If you need to run an additional macro on the output of a previous macro, create a nested genrule definition and use the $(location) macro to read the output of the previous macro.
  • Are parentheses okay inside a macro? Inside a macro, parentheses must be balanced. Parentheses which are part of a quoted string are ignored.
  • Is white space okay inside a macro? Macro arguments are white space separated, so arguments which contain white space must be quoted.
  • Are nested quotes allowed? A single level of nested quotes is allowed, such as "My name is 'Buck'." or 'My name is "Buck".'). Note that when you use a macro in a BUCK file, you must ensure that quotes are properly escaped, so that the shell command that uses the macro forms a proper string.

Extended Backus—Naur form

The Extended Backus—Naur form (EBNF) grammar for a macro is as follows:

macro = "$(", macro_name, whitespace, [arg_list], ")";
macro_name = {all_ascii_chars - whitespace - parens};
whitespace = "\t" | "\n" | " " | "\r";
parens = "(" | ")";
arg_list = arg | arg, whitespace, arg_list;
arg = {all_ascii_chars - whitespace - parens}
      | "(", arg, ")"
      | "\"", [{-"\""}], "\""
      | "'", [{-"'"}], "'";