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, providing additional functionality such as referencing the output paths of other rules. String parameter macros have the form $(macro[ argument]). For rules that support string parameter macros, you can use a backslash at any time to prevent expansion (e.g. \$(dirname ...)). The following macros are supported:
  • $(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 class abi jars that are in the classpath of the given target
  • $(exe //:foo) expands to the executable output of given target if it exists
  • $(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 the macro is used in. Only useful for rules which allows named supplementary outputs.
  • $(query_targets "deps(//:foo)") executes the given query and expands to the list of targets that match. See more information below.
  • $(query_outputs "deps(//:foo)") executes the given query and expands to the output files of the list of targets that match. See more information below.
  • $(query_targets_and_outputs [SEPARATOR] "deps(//:foo)") executes the given query and expands to the target name and the output files of the list of targets that match. Targets and paths are separated by SEPARATOR if provided, or a space if it is not.

Arguments

  • String parameter macros may take a space separated list of arguments.

Examples

The following example uses 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',
)
The following example uses a backslash to prevent macro expansion, and hand the dirname subshell command directly to the shell:
genrule(
  name = 'gen',
  out = 'out.txt',
  cmd = 'cp $SRCS \$(dirname $OUT)',
  srcs = [
    'test1.txt',
    'test2.txt',
  ],
)
The query_* macros accepts a quoted query expression which supports the following query functions:
  • attrfilter
  • deps
  • except
  • classpath
  • intersect
  • filter
  • kind
  • set
  • union
The classpath function is used to query the classpath of java_libraryrules. It takes an optional second argument to limit the depth of the traversal. Example queries
cmd = '$(query_targets "deps(:foo)")'
cmd = '$(query_outputs "filter(name_regex, deps(:bar))")'
cmd = '$(query_targets "attrfilter(annotation_processors, com.foo.Processor, deps(:app))")'

Technical Details

The 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, ")"
      | "\"", [{-"\""}], "\""
      | "'", [{-"'"}], "'";

FAQs

  • 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 a second macro on the output of another macro, create a nested genrule definition and use the $(location) macro to read the output of the first one.
  • Are parens okay inside a macro? Inside a macro, parentheses must be balanced. Parentheses which are part of a quoted string are ignored.
  • Is whitespace okay inside a macro? Macro args are whitespace separated, so args which contain whitespace must be quoted.
  • Are nested quotes allowed? A single level of nested quotes is allowed (e.g. "My name is 'Buck'." or 'My name is "Buck".'). Note that when you use the macro in a BUCK file, you must ensure that these quotes are properly escaped, so that the command which uses the macro forms a proper string.