diff options
author | 2016-01-15 15:54:12 +0000 | |
---|---|---|
committer | 2016-01-15 22:29:37 +0000 | |
commit | 67e6f98d7659ac41154f93c39e548ba0ecc43c80 (patch) | |
tree | aa1804d5058d3e0d53c58ab1af4e6301da1fd190 /site | |
parent | 8cc0541da1ec912568c8df2fc13a9b72b668cda2 (diff) |
Add native.rule(NAME), which returns the attributes of a previously defined rule.
Add native.rules(), which returns all previously defined rules.
These primitives can be used to write Skylark extensions that aggregate over the contents of a BUILD file, eg.
def instantiate_if_needed(name):
n = name + "_wrapped"
if not native.rule(n):
py_test(name = n , ... )
def archive_cc_src_files(tag):
all_src = []
for r in native.rules().values():
if tag in r["tags"] and r["kind"] == "cc_library":
all_src.append(r["srcs"])
native.genrule(cmd = "zip $@ $^", srcs = all_src, outs = ["out.zip"])
RELNOTES: Support aggregation over existing rules in Skylark extensions
through native.rules and native.rule.
--
MOS_MIGRATED_REVID=112249050
Diffstat (limited to 'site')
-rw-r--r-- | site/docs/skylark/cookbook.md | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/site/docs/skylark/cookbook.md b/site/docs/skylark/cookbook.md index 4952d91a20..c4f718faea 100644 --- a/site/docs/skylark/cookbook.md +++ b/site/docs/skylark/cookbook.md @@ -59,6 +59,76 @@ load("/pkg/extension", "macro") macro(name = "myrule") ``` +## <a name="conditional-instantiation"></a>Conditional instantiation.</a> + +Macros can look at previously instantiated rules. This is done with +`native.rule`, which returns information on a single rule defined in the same +`BUILD` file, eg., + +```python +native.rule("descriptor_proto") +``` + +This is useful to avoid instantiating the same rule twice, which is an +error. For example, the following rule will simulate a test suite, instantiating +tests for diverse flavors of the same test. + +`extension.bzl`: + +```python +def system_test(test_file, flavor): + n = "system_test_%s_%s_test" % (test_file, flavor) + if native.rule(n) == None: + native.py_test( + name = n, + srcs = [ "test_driver.py", test_file ], + args = [ "--flavor=" + flavor]) + return n + +def system_test_suite(name, flavors=["default"], test_files): + ts = [] + for flavor in flavors: + for test in test_files: + ts.append(system_test(name, flavor, test)) + native.test_suite(name = name, tests = ts) +``` + +In the following BUILD file, note how `(fast, basic_test.py)` is emitted for +both the `smoke` test suite and the `thorough` test suite. + +```python +load("/pkg/extension", "system_test_suite") + +# Run all files through the 'fast' flavor. +system_test_suite("smoke", flavors=["fast"], glob(["*_test.py"])) + +# Run the basic test through all flavors. +system_test_suite("thorough", flavors=["fast", "debug", "opt"], ["basic_test.py"]) +``` + + +## <a name="aggregation"></a>Aggregating over the BUILD file.</a> + +Macros can collect information from the BUILD file as processed so far. We call +this aggregation. The typical example is collecting data from all rules of a +certain kind. This is done by calling `native.rules`, which returns a +dictionary representing all rules defined so far in the current BUILD file. The +dictionary has entries of the form `name` => `rule`, with the values using the +same format as `native.rule`. + +```python +def archive_cc_src_files(tag): + """Create an archive of all C++ sources that have the given tag.""" + all_src = [] + for r in native.rules().values(): + if tag in r["tags"] and r["kind"] == "cc_library": + all_src.append(r["srcs"]) + native.genrule(cmd = "zip $@ $^", srcs = all_src, outs = ["out.zip"]) +``` + +Since `native.rules` constructs a potentially large dictionary, you should avoid +calling it repeatedly within BUILD file. + ## <a name="empty"></a>Empty rule Minimalist example of a rule that does nothing. If you build it, the target will |