diff options
author | 2015-06-17 13:58:08 +0000 | |
---|---|---|
committer | 2015-06-17 15:24:47 +0000 | |
commit | 09997a0ae07e4222cf1d27290f53e93c6a517d91 (patch) | |
tree | 3781ef7faf6b795046b0554c69c144c8fa616eb5 /site | |
parent | 9c37ab153ed19a8018e2c76891b63f66042d8f29 (diff) |
Skylark cookbook example: Computed dependencies
--
MOS_MIGRATED_REVID=96202821
Diffstat (limited to 'site')
-rw-r--r-- | site/docs/skylark/cookbook.md | 99 |
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 |