mirror of
https://github.com/bazel-contrib/bazel-lib
synced 2024-11-30 01:41:21 +00:00
3af9e00308
* docs: clarify write_source_files output constraint For both the "write_source_files" rule's "files" attribute and the "write_source_file" rule's "out_file" attribute, we ensure that the destination files and directories to which we'll write sit within the same containing Bazel package as the Bazel target requesting this writing. Clarify the documentation for each attribute to make it clear that we're constraining the destinations and not the sources of the content to be written. * Update lib/write_source_files.bzl --------- Co-authored-by: Derek Cormier <derek@aspect.dev>
170 lines
5.7 KiB
Python
170 lines
5.7 KiB
Python
"Public API for write_source_files"
|
|
|
|
load(
|
|
"//lib/private:write_source_file.bzl",
|
|
_write_source_file = "write_source_file",
|
|
)
|
|
|
|
def write_source_files(
|
|
name,
|
|
files = {},
|
|
executable = False,
|
|
additional_update_targets = [],
|
|
suggested_update_target = None,
|
|
diff_test = True,
|
|
**kwargs):
|
|
"""Write one or more files and/or directories to the source tree.
|
|
|
|
By default, `diff_test` targets are generated that ensure the source tree files and/or directories to be written to
|
|
are up to date and the rule also checks that all source tree files and/or directories to be written to exist.
|
|
To disable the exists check and up-to-date tests set `diff_test` to `False`.
|
|
|
|
Usage:
|
|
|
|
```starlark
|
|
load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files")
|
|
|
|
write_source_files(
|
|
name = "write_foobar",
|
|
files = {
|
|
"foobar.json": "//some/generated:file",
|
|
},
|
|
)
|
|
```
|
|
|
|
To update the source file, run:
|
|
|
|
```bash
|
|
bazel run //:write_foobar
|
|
```
|
|
|
|
The generated `diff_test` will fail if the file is out of date and print out instructions on
|
|
how to update it.
|
|
|
|
If the file does not exist, Bazel will fail at analysis time and print out instructions on
|
|
how to create it.
|
|
|
|
You can declare a tree of generated source file targets:
|
|
|
|
```starlark
|
|
load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files")
|
|
|
|
write_source_files(
|
|
name = "write_all",
|
|
additional_update_targets = [
|
|
# Other write_source_files targets to run when this target is run
|
|
"//a/b/c:write_foo",
|
|
"//a/b:write_bar",
|
|
]
|
|
)
|
|
```
|
|
|
|
And update them with a single run:
|
|
|
|
```bash
|
|
bazel run //:write_all
|
|
```
|
|
|
|
When a file is out of date, you can leave a suggestion to run a target further up in the tree by specifying `suggested_update_target`.
|
|
For example,
|
|
|
|
```starlark
|
|
write_source_files(
|
|
name = "write_foo",
|
|
files = {
|
|
"foo.json": ":generated-foo",
|
|
},
|
|
suggested_update_target = "//:write_all"
|
|
)
|
|
```
|
|
|
|
A test failure from `foo.json` being out of date will yield the following message:
|
|
|
|
```
|
|
//a/b:c:foo.json is out of date. To update this and other generated files, run:
|
|
|
|
bazel run //:write_all
|
|
|
|
To update *only* this file, run:
|
|
|
|
bazel run //a/b/c:write_foo
|
|
```
|
|
|
|
If you have many `write_source_files` targets that you want to update as a group, we recommend wrapping
|
|
`write_source_files` in a macro that defaults `suggested_update_target` to the umbrella update target.
|
|
|
|
NOTE: If you run formatters or linters on your codebase, it is advised that you exclude/ignore the outputs of this
|
|
rule from those formatters/linters so as to avoid causing collisions and failing tests.
|
|
|
|
Args:
|
|
name: Name of the runnable target that creates or updates the source tree files and/or directories.
|
|
|
|
files: A dict where the keys are files or directories in the source tree to write to and the values are labels
|
|
pointing to the desired content, typically file or directory outputs of other targets.
|
|
|
|
Destination files and directories must be within the same containing Bazel package as this target.
|
|
|
|
executable: Whether source tree files written should be made executable.
|
|
|
|
This applies to all source tree files written by this target. This attribute is not propagated to `additional_update_targets`.
|
|
|
|
To set different executable permissions on different source tree files use multiple `write_source_files` targets.
|
|
|
|
additional_update_targets: List of other `write_source_files` or `write_source_file` targets to call in the same run.
|
|
|
|
suggested_update_target: Label of the `write_source_files` or `write_source_file` target to suggest running when files are out of date.
|
|
|
|
diff_test: Test that the source tree files and/or directories exist and are up to date.
|
|
|
|
**kwargs: Other common named parameters such as `tags` or `visibility`
|
|
"""
|
|
|
|
single_update_target = len(files.keys()) == 1
|
|
update_targets = []
|
|
test_targets = []
|
|
for i, pair in enumerate(files.items()):
|
|
out_file, in_file = pair
|
|
|
|
this_suggested_update_target = suggested_update_target
|
|
if single_update_target:
|
|
update_target_name = name
|
|
else:
|
|
update_target_name = "%s_%d" % (name, i)
|
|
update_targets.append(update_target_name)
|
|
if not this_suggested_update_target:
|
|
this_suggested_update_target = name
|
|
|
|
# Runnable target that writes to the out file to the source tree
|
|
test_target = _write_source_file(
|
|
name = update_target_name,
|
|
in_file = in_file,
|
|
out_file = out_file,
|
|
executable = executable,
|
|
additional_update_targets = additional_update_targets if single_update_target else [],
|
|
suggested_update_target = this_suggested_update_target,
|
|
diff_test = diff_test,
|
|
**kwargs
|
|
)
|
|
|
|
if test_target:
|
|
test_targets.append(test_target)
|
|
|
|
if len(test_targets) > 0:
|
|
native.test_suite(
|
|
name = "%s_tests" % name,
|
|
tests = test_targets,
|
|
visibility = kwargs.get("visibility"),
|
|
tags = kwargs.get("tags"),
|
|
)
|
|
|
|
if not single_update_target:
|
|
_write_source_file(
|
|
name = name,
|
|
additional_update_targets = update_targets + additional_update_targets,
|
|
suggested_update_target = suggested_update_target,
|
|
diff_test = False,
|
|
**kwargs
|
|
)
|
|
|
|
write_source_file = _write_source_file
|