feat: replace default_info_files with output_files which adds output_group attribute (#50)

This commit is contained in:
Greg Magolan 2022-03-15 17:36:22 -07:00 committed by GitHub
parent 3b93ee0baa
commit bda5c632be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 244 additions and 185 deletions

View File

@ -49,8 +49,8 @@ stardoc_with_diff_test(
)
stardoc_with_diff_test(
name = "default_info_files",
bzl_library_target = "//lib:default_info_files",
name = "output_files",
bzl_library_target = "//lib:output_files",
)
update_docs()

View File

@ -1,49 +0,0 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
A rule that provides file(s) from a given target's DefaultInfo
<a id="#default_info_files"></a>
## default_info_files
<pre>
default_info_files(<a href="#default_info_files-name">name</a>, <a href="#default_info_files-paths">paths</a>, <a href="#default_info_files-target">target</a>)
</pre>
A rule that provides file(s) from a given target's DefaultInfo
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="default_info_files-name"></a>name | A unique name for this target. | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required | |
| <a id="default_info_files-paths"></a>paths | the paths of the files to provide in the DefaultInfo of the target relative to its root | List of strings | required | |
| <a id="default_info_files-target"></a>target | the target to look in for requested paths in its' DefaultInfo | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | required | |
<a id="#make_default_info_files"></a>
## make_default_info_files
<pre>
make_default_info_files(<a href="#make_default_info_files-name">name</a>, <a href="#make_default_info_files-target">target</a>, <a href="#make_default_info_files-paths">paths</a>)
</pre>
Helper function to generate a default_info_files target and return its label.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="make_default_info_files-name"></a>name | unique name for the generated <code>default_info_files</code> target. | none |
| <a id="make_default_info_files-target"></a>target | the target to look in for requested paths in its' DefaultInfo | none |
| <a id="make_default_info_files-paths"></a>paths | the paths of the files to provide in the DefaultInfo of the target relative to its root | none |
**RETURNS**
The label `name`

View File

@ -50,7 +50,7 @@ Joins a label pointing to a TreeArtifact with a path nested within that director
## make_directory_path
<pre>
make_directory_path(<a href="#make_directory_path-name">name</a>, <a href="#make_directory_path-directory">directory</a>, <a href="#make_directory_path-path">path</a>)
make_directory_path(<a href="#make_directory_path-name">name</a>, <a href="#make_directory_path-directory">directory</a>, <a href="#make_directory_path-path">path</a>, <a href="#make_directory_path-kwargs">kwargs</a>)
</pre>
Helper function to generate a directory_path target and return its label.
@ -60,9 +60,10 @@ Helper function to generate a directory_path target and return its label.
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="make_directory_path-name"></a>name | Unique name for the generated <code>directory_path</code> target. | none |
| <a id="make_directory_path-directory"></a>directory | a TreeArtifact (ctx.actions.declare_directory) | none |
| <a id="make_directory_path-path"></a>path | path relative to the directory | none |
| <a id="make_directory_path-name"></a>name | unique name for the generated <code>directory_path</code> target | none |
| <a id="make_directory_path-directory"></a>directory | <code>directory</code> attribute passed to generated <code>directory_path</code> target | none |
| <a id="make_directory_path-path"></a>path | <code>path</code> attribute passed to generated <code>directory_path</code> target | none |
| <a id="make_directory_path-kwargs"></a>kwargs | parameters to pass to generated <code>output_files</code> target | none |
**RETURNS**
@ -74,7 +75,7 @@ The label `name`
## make_directory_paths
<pre>
make_directory_paths(<a href="#make_directory_paths-name">name</a>, <a href="#make_directory_paths-dict">dict</a>)
make_directory_paths(<a href="#make_directory_paths-name">name</a>, <a href="#make_directory_paths-dict">dict</a>, <a href="#make_directory_paths-kwargs">kwargs</a>)
</pre>
Helper function to convert a dict of directory to path mappings to directory_path targets and labels.
@ -128,6 +129,7 @@ and the list of targets is returned,
| :------------- | :------------- | :------------- |
| <a id="make_directory_paths-name"></a>name | The target name to use for the generated targets & labels.<br><br>The names are generated as zero-indexed <code>name + "_" + i</code> | none |
| <a id="make_directory_paths-dict"></a>dict | The dictionary of directory keys to path or path list values. | none |
| <a id="make_directory_paths-kwargs"></a>kwargs | additional parameters to pass to each generated target | none |
**RETURNS**

51
docs/output_files.md Normal file
View File

@ -0,0 +1,51 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
A rule that provides file(s) specific via DefaultInfo from a given target's DefaultInfo or OutputGroupInfo
<a id="#output_files"></a>
## output_files
<pre>
output_files(<a href="#output_files-name">name</a>, <a href="#output_files-output_group">output_group</a>, <a href="#output_files-paths">paths</a>, <a href="#output_files-target">target</a>)
</pre>
A rule that provides file(s) specific via DefaultInfo from a given target's DefaultInfo or OutputGroupInfo
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="output_files-name"></a>name | A unique name for this target. | <a href="https://bazel.build/docs/build-ref.html#name">Name</a> | required | |
| <a id="output_files-output_group"></a>output_group | if set, we look in the specified output group for paths instead of DefaultInfo | String | optional | "" |
| <a id="output_files-paths"></a>paths | the paths of the file(s), relative to their roots, to provide via DefaultInfo from the given target's DefaultInfo or OutputGroupInfo | List of strings | required | |
| <a id="output_files-target"></a>target | the target to look in for requested paths in its' DefaultInfo or OutputGroupInfo | <a href="https://bazel.build/docs/build-ref.html#labels">Label</a> | required | |
<a id="#make_output_files"></a>
## make_output_files
<pre>
make_output_files(<a href="#make_output_files-name">name</a>, <a href="#make_output_files-target">target</a>, <a href="#make_output_files-paths">paths</a>, <a href="#make_output_files-kwargs">kwargs</a>)
</pre>
Helper function to generate a output_files target and return its label.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="make_output_files-name"></a>name | unique name for the generated <code>output_files</code> target | none |
| <a id="make_output_files-target"></a>target | <code>target</code> attribute passed to generated <code>output_files</code> target | none |
| <a id="make_output_files-paths"></a>paths | <code>paths</code> attribute passed to generated <code>output_files</code> target | none |
| <a id="make_output_files-kwargs"></a>kwargs | parameters to pass to generated <code>output_files</code> target | none |
**RETURNS**
The label `name`

View File

@ -64,10 +64,10 @@ bzl_library(
)
bzl_library(
name = "default_info_files",
srcs = ["default_info_files.bzl"],
name = "output_files",
srcs = ["output_files.bzl"],
visibility = ["//visibility:public"],
deps = ["//lib/private:default_info_files"],
deps = ["//lib/private:output_files"],
)
bzl_library(

View File

@ -1,11 +0,0 @@
"""A rule that provides file(s) from a given target's DefaultInfo
"""
load(
"//lib/private:default_info_files.bzl",
_default_info_files = "default_info_files",
_make_default_info_files = "make_default_info_files",
)
default_info_files = _default_info_files
make_default_info_files = _make_default_info_files

11
lib/output_files.bzl Normal file
View File

@ -0,0 +1,11 @@
"""A rule that provides file(s) specific via DefaultInfo from a given target's DefaultInfo or OutputGroupInfo
"""
load(
"//lib/private:output_files.bzl",
_make_output_files = "make_output_files",
_output_files = "output_files",
)
output_files = _output_files
make_output_files = _make_output_files

View File

@ -10,8 +10,8 @@ bzl_library(
srcs = ["copy_to_directory.bzl"],
visibility = ["//lib:__subpackages__"],
deps = [
":default_info_files",
":directory_path",
":output_files",
":paths",
"@bazel_skylib//lib:paths",
],
@ -66,8 +66,8 @@ bzl_library(
srcs = ["write_source_file.bzl"],
visibility = ["//lib:__subpackages__"],
deps = [
":default_info_files",
":directory_path",
":output_files",
"//lib:utils",
],
)
@ -86,8 +86,8 @@ bzl_library(
)
bzl_library(
name = "default_info_files",
srcs = ["default_info_files.bzl"],
name = "output_files",
srcs = ["output_files.bzl"],
visibility = ["//lib:__subpackages__"],
deps = ["//lib:utils"],
)

View File

@ -1,70 +0,0 @@
"""default_info_files implementation
"""
load("//lib:utils.bzl", _to_label = "to_label")
def _default_info_files(ctx):
files = []
for path in ctx.attr.paths:
file = find_short_path_in_default_info(
ctx.attr.target,
path,
)
if not file:
fail("%s file not found within the DefaultInfo of %s" % (ctx.attr.path, ctx.attr.target))
files.append(file)
return [DefaultInfo(
files = depset(direct = files),
runfiles = ctx.runfiles(files = files),
)]
default_info_files = rule(
doc = "A rule that provides file(s) from a given target's DefaultInfo",
implementation = _default_info_files,
attrs = {
"target": attr.label(
doc = "the target to look in for requested paths in its' DefaultInfo",
mandatory = True,
),
"paths": attr.string_list(
doc = "the paths of the files to provide in the DefaultInfo of the target relative to its root",
mandatory = True,
allow_empty = False,
),
},
provides = [DefaultInfo],
)
def make_default_info_files(name, target, paths):
"""Helper function to generate a default_info_files target and return its label.
Args:
name: unique name for the generated `default_info_files` target.
target: the target to look in for requested paths in its' DefaultInfo
paths: the paths of the files to provide in the DefaultInfo of the target relative to its root
Returns:
The label `name`
"""
default_info_files(
name = name,
target = target,
paths = paths,
)
return _to_label(name)
def find_short_path_in_default_info(default_info, short_path):
"""Helper function find a file in a DefaultInfo by short path
Args:
default_info: a DefaultInfo
short_path: the short path (path relative to root) to search for
Returns:
The File if found else None
"""
if default_info.files:
for file in default_info.files.to_list():
if file.short_path == short_path:
return file
return None

View File

@ -36,13 +36,14 @@ Otherwise there is no way to give a Bazel label for it.""",
provides = [DirectoryPathInfo],
)
def make_directory_path(name, directory, path):
def make_directory_path(name, directory, path, **kwargs):
"""Helper function to generate a directory_path target and return its label.
Args:
name: Unique name for the generated `directory_path` target.
directory: a TreeArtifact (ctx.actions.declare_directory)
path: path relative to the directory
name: unique name for the generated `directory_path` target
directory: `directory` attribute passed to generated `directory_path` target
path: `path` attribute passed to generated `directory_path` target
**kwargs: parameters to pass to generated `output_files` target
Returns:
The label `name`
@ -51,10 +52,11 @@ def make_directory_path(name, directory, path):
name = name,
directory = directory,
path = path,
**kwargs
)
return _to_label(name)
def make_directory_paths(name, dict):
def make_directory_paths(name, dict, **kwargs):
"""Helper function to convert a dict of directory to path mappings to directory_path targets and labels.
For example,
@ -104,6 +106,7 @@ def make_directory_paths(name, dict):
The names are generated as zero-indexed `name + "_" + i`
dict: The dictionary of directory keys to path or path list values.
**kwargs: additional parameters to pass to each generated target
Returns:
The label of the generated `directory_path` targets named `name + "_" + i`
@ -124,5 +127,6 @@ def make_directory_paths(name, dict):
"%s_%d" % (name, i),
directory,
path,
**kwargs
))
return labels

View File

@ -0,0 +1,87 @@
"""output_files implementation
"""
load("//lib:utils.bzl", _to_label = "to_label")
def _output_files(ctx):
files = []
files_depset = depset()
if ctx.attr.output_group:
if OutputGroupInfo not in ctx.attr.target:
msg = "%s output_group is specified but %s does not provide an OutputGroupInfo" % (ctx.attr.output_group, ctx.attr.target)
fail(msg)
if ctx.attr.output_group not in ctx.attr.target[OutputGroupInfo]:
msg = "%s output_group is specified but %s does not provide this output group" % (ctx.attr.output_group, ctx.attr.target)
fail(msg)
files_depset = ctx.attr.target[OutputGroupInfo][ctx.attr.output_group]
else:
files_depset = ctx.attr.target[DefaultInfo].files
for path in ctx.attr.paths:
file = _find_short_path_in_files_depset(files_depset, path)
if not file:
if ctx.attr.output_group:
msg = "%s file not found within the %s output group of %s" % (path, ctx.attr.output_group, ctx.attr.target)
else:
msg = "%s file not found within the DefaultInfo of %s" % (path, ctx.attr.target)
fail(msg)
files.append(file)
return [DefaultInfo(
files = depset(direct = files),
runfiles = ctx.runfiles(files = files),
)]
output_files = rule(
doc = "A rule that provides file(s) specific via DefaultInfo from a given target's DefaultInfo or OutputGroupInfo",
implementation = _output_files,
attrs = {
"target": attr.label(
doc = "the target to look in for requested paths in its' DefaultInfo or OutputGroupInfo",
mandatory = True,
),
"paths": attr.string_list(
doc = "the paths of the file(s), relative to their roots, to provide via DefaultInfo from the given target's DefaultInfo or OutputGroupInfo",
mandatory = True,
allow_empty = False,
),
"output_group": attr.string(
doc = "if set, we look in the specified output group for paths instead of DefaultInfo",
),
},
provides = [DefaultInfo],
)
def make_output_files(name, target, paths, **kwargs):
"""Helper function to generate a output_files target and return its label.
Args:
name: unique name for the generated `output_files` target
target: `target` attribute passed to generated `output_files` target
paths: `paths` attribute passed to generated `output_files` target
**kwargs: parameters to pass to generated `output_files` target
Returns:
The label `name`
"""
output_files(
name = name,
target = target,
paths = paths,
**kwargs
)
return _to_label(name)
def _find_short_path_in_files_depset(files_depset, short_path):
"""Helper function find a file in a DefaultInfo by short path
Args:
files_depset: a depset
short_path: the short path (path relative to root) to search for
Returns:
The File if found else None
"""
if files_depset:
for file in files_depset.to_list():
if file.short_path == short_path:
return file
return None

View File

@ -1,30 +0,0 @@
"""A simple rule that generates provides a DefaultOutput with some files"""
def _impl(ctx):
if len(ctx.attr.out_files) != len(ctx.attr.out_contents):
fail("Number of out_files must match number of out_contents")
outputs = []
for i, file in enumerate(ctx.attr.out_files):
content = ctx.attr.out_contents[i]
out = ctx.actions.declare_file(file)
# ctx.actions.write creates a FileWriteAction which uses UTF-8 encoding.
ctx.actions.write(
output = out,
content = content,
)
outputs.append(out)
return [DefaultInfo(
files = depset(direct = outputs),
runfiles = ctx.runfiles(files = outputs),
)]
default_output_gen = rule(
implementation = _impl,
provides = [DefaultInfo],
attrs = {
"out_files": attr.string_list(),
"out_contents": attr.string_list(),
},
)

View File

@ -0,0 +1,34 @@
"""A simple rule that generates provides a DefaultOutput with some files"""
def _impl(ctx):
if len(ctx.attr.output_files) != len(ctx.attr.output_contents):
fail("Number of output_files must match number of output_contents")
outputs = []
for i, file in enumerate(ctx.attr.output_files):
content = ctx.attr.output_contents[i]
out = ctx.actions.declare_file(file)
# ctx.actions.write creates a FileWriteAction which uses UTF-8 encoding.
ctx.actions.write(
output = out,
content = content,
)
outputs.append(out)
provide = []
if ctx.attr.output_group:
kwargs = {ctx.attr.output_group: depset(outputs)}
provide.append(OutputGroupInfo(**kwargs))
else:
provide.append(DefaultInfo(files = depset(outputs)))
return provide
generate_outputs = rule(
implementation = _impl,
provides = [DefaultInfo],
attrs = {
"output_files": attr.string_list(),
"output_contents": attr.string_list(),
"output_group": attr.string(),
},
)

View File

@ -1,9 +1,9 @@
load("//lib/tests/write_source_files:write_source_file_test.bzl", "write_source_file_test")
load("//lib/tests:default_output_gen.bzl", "default_output_gen")
load("//lib/tests:generate_outputs.bzl", "generate_outputs")
load("//lib:write_source_files.bzl", "write_source_files")
load("//lib:copy_to_directory.bzl", "copy_to_directory")
load("//lib:directory_path.bzl", "directory_path")
load("//lib:default_info_files.bzl", "default_info_files")
load("//lib:output_files.bzl", "output_files")
genrule(
name = "a-desired",
@ -11,20 +11,20 @@ genrule(
cmd = "echo 'console.log(\"a*\");' > $@",
)
default_output_gen(
generate_outputs(
name = "b_c-desired",
out_contents = [
output_contents = [
"""console.log(\"b*\");
""",
"not used!",
],
out_files = [
output_files = [
"b-desired.js",
"c-desired.js",
],
)
default_info_files(
output_files(
name = "b-desired",
paths = ["%s/b-desired.js" % package_name()],
target = ":b_c-desired",
@ -61,6 +61,27 @@ directory_path(
path = "f-contained.js",
)
generate_outputs(
name = "g_h-desired",
output_contents = [
"""console.log(\"g*\");
""",
"not used!",
],
output_files = [
"g-desired.js",
"h-desired.js",
],
output_group = "gh_output_group",
)
output_files(
name = "g-desired",
output_group = "gh_output_group",
paths = ["%s/g-desired.js" % package_name()],
target = ":g_h-desired",
)
write_source_file_test(
name = "write_to_source_files_a_test",
in_file = ":a-desired",
@ -79,6 +100,12 @@ write_source_file_test(
out_file = "f.js",
)
write_source_file_test(
name = "write_to_source_files_g_test",
in_file = ":g-desired",
out_file = "g.js",
)
write_source_files(
name = "macro_smoke_test",
additional_update_targets = [
@ -89,5 +116,6 @@ write_source_files(
"b2.js": ":b-desired",
"e2_dir": ":e_dir-desired",
"f2.js": ":f-desired",
"g2.js": ":g-desired",
},
)

View File

@ -0,0 +1 @@
console.log("g");

View File

@ -0,0 +1 @@
console.log("g*");