Matthew
Matthew

Reputation: 2810

How can I include the current workspace name in the default argument value of a rule?

Let's say I have a rule:

blah = rule(
    attrs = {
        "foo": attr.string(default = "@HELP@"),
    },
)

I want the default value of foo to contain the name of the workspace that invokes the rule. How can I accomplish this?

(Note: An acceptable approach is to leave a placeholder in the value and replace it when the rule uses the attribute, but I can't figure out how to get the current workspace there either. The closest I can find is ctx.label.workspace_root, but that is empty for the "main" workspace, and e.g. external/foo for other things.)

ctx.workspace_name does not give the correct answers. For example, if I print("'%s' -> '%s'", (ctx.label.workspace_root, ctx.workspace_name)), I get results like:

'externals/foo' -> 'main'
'externals/bar' -> 'main'

...which is wrong; those should be 'foo' and 'bar', not 'main' ('main' being my main/root workspace). Note that labels from those contexts are e.g. '@foo//:foo', so Bazel does apparently know the correct workspace name.

Upvotes: 1

Views: 840

Answers (2)

Matthew
Matthew

Reputation: 2810

As far as getting the workspace name, this seems sub-optimal, but also seems to work:

def _workspace(ctx):
    """Compute name of current workspace."""

    # Check for meaningful workspace_root
    workspace = ctx.label.workspace_root.split("/")[-1]
    if len(workspace):
        return workspace

    # If workspace_root is empty, assume we are the root workspace
    return ctx.workspace_name

Per Kristina's answer and comment in the original question, this can then be used to replace a placeholder in the parameter value.

Upvotes: 1

kris
kris

Reputation: 23601

You can use a placeholder attribute and then use ctx.workspace_name in the implementation.

def _impl(ctx):
  print("ws: %s" % ctx.workspace_name)

blah = rule(
    implementation = _impl,
)

Upvotes: 1

Related Questions