如何将当前工作区名称包含在规则的默认参数值中?

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

假设我有一个规则:

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

我希望 foo 的默认值包含调用规则的工作区的名称。我怎样才能做到这一点?

(注意:一种可接受的方法是在值中保留一个占位符,并在规则使用该属性时替换它,但我也不知道如何在那里获取当前工作区。我能找到的最接近的是 ctx.label.workspace_root,但对于 "main" 工作区来说是空的,例如 external/foo 对于其他东西。)

ctx.workspace_name 没有给出正确答案。例如,如果我 print("'%s' -> '%s'", (ctx.label.workspace_root, ctx.workspace_name)),我会得到如下结果:

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

...这是错误的;那些应该是 'foo' 和 'bar',而不是 'main'('main' 是我的 main/root 工作区)。请注意,来自这些上下文的标签是例如'@foo//:foo',所以 Bazel 显然知道正确的工作区名称。

您可以使用占位符属性,然后在实现中使用 ctx.workspace_name

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

blah = rule(
    implementation = _impl,
)

就获取工作区名称而言,这似乎不是最佳选择,但似乎也有效:

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

根据 Kristina 在原始问题中的回答和评论,这可以用来替换参数值中的占位符。