mirror of
https://github.com/bazel-contrib/bazel-lib
synced 2024-11-30 01:41:21 +00:00
141 lines
4.7 KiB
Python
141 lines
4.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 = {},
|
|
additional_update_targets = [],
|
|
suggested_update_target = None,
|
|
diff_test = True,
|
|
**kwargs):
|
|
"""Write to one or more files or folders in the source tree. Stamp out tests that ensure the sources exist and are up to date.
|
|
|
|
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
|
|
```
|
|
|
|
A test will fail if the source file doesn't exist or if it's out of date with instructions on how to create/update 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`. E.g.,
|
|
|
|
```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 sources 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 executable target that creates or updates the source file
|
|
files: A dict where the keys are source files or folders to write to and the values are labels pointing to the desired content.
|
|
Sources must be within the same bazel package as the target.
|
|
additional_update_targets: (Optional) List of other write_source_file or other executable updater targets to call in the same run
|
|
suggested_update_target: (Optional) Label of the write_source_file target to suggest running when files are out of date
|
|
diff_test: (Optional) Generate a test target to check that the source file(s) exist and are up to date with the generated files(s).
|
|
**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,
|
|
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
|
|
)
|