134 lines
3.8 KiB
Python
134 lines
3.8 KiB
Python
"""Rule and corresponding provider that joins a label pointing to a TreeArtifact
|
|
with a path nested within that directory
|
|
"""
|
|
|
|
load("//lib:utils.bzl", _to_label = "to_label")
|
|
|
|
DirectoryPathInfo = provider(
|
|
doc = "Joins a label pointing to a TreeArtifact with a path nested within that directory.",
|
|
fields = {
|
|
"directory": "a TreeArtifact (ctx.actions.declare_directory)",
|
|
"path": "path relative to the directory",
|
|
},
|
|
)
|
|
|
|
def _directory_path(ctx):
|
|
if not ctx.file.directory.is_directory:
|
|
msg = "Expected directory to be a TreeArtifact (ctx.actions.declare_directory) but {} is either a source file or does not exist.".format(ctx.file.directory)
|
|
fail(msg)
|
|
return [DirectoryPathInfo(path = ctx.attr.path, directory = ctx.file.directory)]
|
|
|
|
directory_path = rule(
|
|
doc = """Provide DirectoryPathInfo to reference some path within a directory.
|
|
|
|
Otherwise there is no way to give a Bazel label for it.""",
|
|
implementation = _directory_path,
|
|
attrs = {
|
|
"directory": attr.label(
|
|
doc = "a TreeArtifact (ctx.actions.declare_directory)",
|
|
mandatory = True,
|
|
allow_single_file = True,
|
|
),
|
|
"path": attr.string(
|
|
doc = "path relative to the directory",
|
|
mandatory = True,
|
|
),
|
|
},
|
|
provides = [DirectoryPathInfo],
|
|
)
|
|
|
|
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: `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`
|
|
"""
|
|
directory_path(
|
|
name = name,
|
|
directory = directory,
|
|
path = path,
|
|
**kwargs
|
|
)
|
|
return _to_label(name)
|
|
|
|
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,
|
|
|
|
```
|
|
make_directory_paths("my_name", {
|
|
"//directory/artifact:target_1": "file/path",
|
|
"//directory/artifact:target_2": ["file/path1", "file/path2"],
|
|
})
|
|
```
|
|
|
|
generates the targets,
|
|
|
|
```
|
|
directory_path(
|
|
name = "my_name_0",
|
|
directory = "//directory/artifact:target_1",
|
|
path = "file/path"
|
|
)
|
|
|
|
directory_path(
|
|
name = "my_name_1",
|
|
directory = "//directory/artifact:target_2",
|
|
path = "file/path1"
|
|
)
|
|
|
|
directory_path(
|
|
name = "my_name_2",
|
|
directory = "//directory/artifact:target_2",
|
|
path = "file/path2"
|
|
)
|
|
```
|
|
|
|
and the list of targets is returned,
|
|
|
|
```
|
|
[
|
|
"my_name_0",
|
|
"my_name_1",
|
|
"my_name_2",
|
|
]
|
|
```
|
|
|
|
Args:
|
|
name: The target name to use for the generated targets & labels.
|
|
|
|
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`
|
|
"""
|
|
labels = []
|
|
pairs = []
|
|
for directory, val in dict.items():
|
|
if type(val) == "list":
|
|
for path in val:
|
|
pairs.append((directory, path))
|
|
elif type(val) == "string":
|
|
pairs.append((directory, val))
|
|
else:
|
|
fail("Value must be a list or string")
|
|
for i, pair in enumerate(pairs):
|
|
directory, path = pair
|
|
labels.append(make_directory_path(
|
|
"%s_%d" % (name, i),
|
|
directory,
|
|
path,
|
|
**kwargs
|
|
))
|
|
return labels
|