diff options
Diffstat (limited to 'site/versions/master/docs/skylark/macros.md')
-rw-r--r-- | site/versions/master/docs/skylark/macros.md | 156 |
1 files changed, 0 insertions, 156 deletions
diff --git a/site/versions/master/docs/skylark/macros.md b/site/versions/master/docs/skylark/macros.md deleted file mode 100644 index 7782198287..0000000000 --- a/site/versions/master/docs/skylark/macros.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -layout: documentation -title: Macros ---- -# Macros - -## Macro creation - -A macro is a function called from the BUILD file that can instantiate rules. -Macros don't give additional power, they are just used for encapsulation and -code reuse. By the end of the [loading phase](concepts.md#evaluation-model), -macros don't exist anymore, and Bazel sees only the set of rules they created. - -Native rules (i.e. rules that don't need a `load()` statement) can be -instantiated from the [native](lib/native.html) module, e.g. - -```python -def my_macro(name, visibility=None): - native.cc_library( - name = name, - srcs = ["main.cc"], - visibility = visibility, - ) -``` - -If you need to know the package name (i.e. which BUILD file is calling the -macro), use the constant [PACKAGE_NAME](lib/globals.html#PACKAGE_NAME). - -## Examples - -* [Macro creating rules](cookbook.md#macro). - -* [Macro creating native rules](cookbook.md#macro_native). - -* [Macro combining multiple rules](cookbook.md#macro_compound). - -## Debugging - -* `bazel query --output=build //my/path:all` will show you how the BUILD file - looks after evaluation. All macros, globs, loops are expanded. Known - limitation: `select` expressions are currently not shown in the output. - -* You may filter the output based on `generator_function` (which function - generated the rules) or `generator_name` (the name attribute of the macro), - e.g. - ```bash - $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)' - ``` - -* To find out where exactly the rule `foo` is generated in a BUILD file, you - can try the following trick. Insert this line near the top of the BUILD - file: `cc_library(name = "foo")`. Run Bazel. You will get an exception when - the rule `foo` is created (due to a name conflict), which will show you the - full stack trace. - -* You can also use [print](lib/globals.html#print) for debugging. It displays - the message as a warning during the loading phase. Except in rare cases, - either remove `print` calls, or make them conditional under a `debugging` - parameter that defaults to `False` before submitting the code to the depot. - -## Errors - -If you want to throw an error, use the [fail](lib/globals.html#fail) function. -Explain clearly to the user what went wrong and how to fix their BUILD file. It -is not possible to catch an error. - -``` -def my_macro(name, deps, visibility=None): - if len(deps) < 2: - fail("Expected at least two values in deps") - # ... -``` - -## Conventions - -* All public functions (functions that don't start with underscore) that - instantiate rules must have a `name` argument. This argument should not be - optional (don't give a default value). - -* Public functions should use a docstring following [Python - conventions](https://www.python.org/dev/peps/pep-0257/#one-line-docstrings). - -* In BUILD files, the `name` argument of the macros must be a keyword argument - (not a positional argument). - -* The `name` attribute of rules generated by a macro should include the name - argument as a prefix. For example, `macro(name = "foo")` can generate a - `cc_library` `foo` and a genrule `foo_gen`. - -* In most cases, optional parameters should have a default value of `None`. - `None` can be passed directly to native rules, which treat it the same as if - you had not passed in any argument. Thus, there is no need to replace it - with `0`, `False`, or `[]` for this purpose. Instead, the macro should defer - to the rules it creates, as their defaults may be complex or may change over - time. Additionally, a parameter that is explicitly set to its default value - looks different than one that is never set (or set to `None`) when accessed - through the query language or build-system internals. - -* Macros should have an optional `visibility` argument. - -## Full example - -The typical use-case for a macro is when you want to reuse a genrule, e.g. - -``` -genrule( - name = "file", - outs = ["file.txt"], - cmd = "$(location generator) some_arg > $@", - tools = [":generator"], -) -``` - -If you want to generate another file with different arguments, you may want to -extract this code to a function. - -The BUILD file will become simply: - -``` -load("//path:generator.bzl", "file_generator") - -file_generator( - name = "file", - arg = "some_arg", -) -``` - -In order to keep BUILD files clean and declarative, you must put the function in -a separate `.bzl` file. For example, write the definition of the macro in -`path/generator.bzl`: - -``` -def file_generator(name, arg, visibility=None): - native.genrule( - name = name, - outs = [name + ".txt"], - cmd = "$(location generator) %s > $@" % arg, - tools = ["//test:generator"], - visibility = visibility, - ) -``` - -When you want to investigate what a macro does, use the following command to -see the expanded form: - -``` -$ bazel query --output=build :file -# /absolute/path/test/ext.bzl:42:3 -genrule( - name = "file", - tools = ["//test:generator"], - outs = ["//test:file.txt"], - cmd = "$(location generator) some_arg > $@", -) -``` - |