aboutsummaryrefslogtreecommitdiffhomepage
path: root/site
diff options
context:
space:
mode:
authorGravatar Laurent Le Brun <laurentlb@google.com>2015-06-17 13:58:08 +0000
committerGravatar John Field <jfield@google.com>2015-06-17 15:24:47 +0000
commit09997a0ae07e4222cf1d27290f53e93c6a517d91 (patch)
tree3781ef7faf6b795046b0554c69c144c8fa616eb5 /site
parent9c37ab153ed19a8018e2c76891b63f66042d8f29 (diff)
Skylark cookbook example: Computed dependencies
-- MOS_MIGRATED_REVID=96202821
Diffstat (limited to 'site')
-rw-r--r--site/docs/skylark/cookbook.md99
1 files changed, 99 insertions, 0 deletions
diff --git a/site/docs/skylark/cookbook.md b/site/docs/skylark/cookbook.md
index d9ae4af181..dafb06a040 100644
--- a/site/docs/skylark/cookbook.md
+++ b/site/docs/skylark/cookbook.md
@@ -409,6 +409,105 @@ execute(
)
```
+## <a name="late-bound"></a>Computed dependencies
+
+Bazel needs to know about all dependencies before doing the analysis phase and
+calling the implementation function. Dependencies can be computed based on the
+rule attributes and the configuration: to do so, use a function as the default
+value of an attribute (the attribute must be private and have type `label` or
+`list of labels`).
+
+The example below computes the md5 sum of a file. The file can be preprocessed
+using a filter. The exact dependencies depend on the filter chosen by the user.
+
+`hash.bzl`:
+
+```python
+_filters = {
+ "comments": Label("//pkg:comments"),
+ "spaces": Label("//pkg:spaces"),
+ "none": None,
+}
+
+def _get_filter(attr_map, cfg):
+ # Return the value for the attribute "_filter_bin"
+ # It can be a label or None.
+ return _filters[attr_map.filter]
+
+def _impl(ctx):
+ src = ctx.file.src
+
+ if not ctx.attr._filter_bin:
+ # Skip the processing
+ processed = src
+ else:
+ processed = ctx.new_file(ctx.label.name + "_processed")
+ # Run the selected binary
+ ctx.action(
+ outputs = [processed],
+ inputs = [ctx.file.src],
+ progress_message="Apply filter '%s'" % ctx.attr.filter,
+ arguments = [ctx.file.src.path, processed.path],
+ executable = ctx.executable._filter_bin)
+
+ # Compute the hash
+ out = ctx.outputs.text
+ ctx.action(
+ outputs = [out],
+ inputs = [processed],
+ command = "md5sum < %s > %s" % (processed.path, out.path))
+
+hash = rule(
+ implementation=_impl,
+ attrs={
+ "filter": attr.string(values=_filters.keys(), default="none"),
+ "src": attr.label(mandatory=True, single_file=True, allow_files=True),
+ "_filter_bin": attr.label(default=_get_filter, executable=True),
+ },
+ outputs = {"text": "%{name}.txt"})
+```
+
+`BUILD`:
+
+```python
+load("/pkg/hash", "hash")
+
+hash(
+ name = "hash",
+ src = "hello.txt",
+ filter = "spaces",
+)
+
+sh_binary(
+ name = "comments",
+ srcs = ["comments.sh"],
+)
+
+sh_binary(
+ name = "spaces",
+ srcs = ["spaces.sh"],
+)
+```
+
+`hello.txt`:
+
+```
+Hello World!
+```
+
+`comments.sh`:
+
+```
+#! /bin/bash
+grep -v '^ *#' $1 > $2 # Remove lines with only a Python-style comment
+```
+
+`spaces.sh`:
+
+```
+#! /bin/bash
+tr -d ' ' < $1 > $2 # Remove spaces
+```
## <a name="mandatory-providers"></a>Mandatory providers