首页 > 解决方案 > Bazel 为包根目录进行变量替换?

问题描述

假设我有一个这样的 Bazel 项目:

tree .
.
├── foo
│   ├── BUILD.bazel
│   └── foo.txt
└── WORKSPACE

1 directory, 3 files

foo/BUILD.bazel

genrule(
  name = "bar",
  srcs = [
    "foo.txt",
  ],
  cmd = "cp foo.txt $@",
  outs = [
    "bar.txt",
  ],
)

我无法建造bazel build //foo:bar

bazel build //foo:bar

...

cp: cannot stat 'foo.txt': No such file or directory

看来,路径cmd必须相对于WORKSPACE根,而不是BUILD根。

这有效:

genrule(
  name = "bar",
  srcs = [
    "foo.txt",
  ],
  # cmd = "cp foo.txt $@",
  cmd = "cp foo/foo.txt $@",
  outs = [
    "bar.txt",
  ],
)

必须指定完整路径很不方便,尤其是当BUILD文件可能被移动时。

能够编写脚本就好像它们在源树中的位置运行一样也很好(当然它们实际上是在沙箱中运行的!)

是否有一个 Make 变量替换可以让我更清楚地指定它?

例如:

genrule(
  name = "bar",
  srcs = [
    "foo.txt",
  ],
  cmd = "cd $(SRCDIR) && cp foo.txt $@",
  outs = [
    "bar.txt",
  ],
)

这里$(SRCDIR)可以扩展为./foo.

请注意,这是一个人为的示例。我不能使用$(SRCS),因为我需要以不同的方式使用输入文件。我也不能使用$<,因为我有不止一次srcs

标签: bazel

解决方案


是的,有这样的 Make 变量。在这种特殊情况下$<是最方便的,因此规则声明将如下所示:

    genrule(
      name = "bar",
      srcs = ["foo.txt"],
      outs = ["bar.txt"],
      cmd = "cp $< $@",
    )

$<如果 srcs 中只有一个文件,可以使用。如果它们更多,则考虑使用$(SRCS)which 将扩展来自 src 的以空格分隔的输入。

此外,还有预定义的路径替换,例如$(execpath)$(rootpath)标签扩展为完整路径。因此,上面提到的代码段看起来类似于:

    genrule(
      name = "bar",
      srcs = ["foo.txt"],
      outs = ["bar.txt"],
      cmd = "cp $(execpath foo.txt) $@",
    )

并且有一个$(location)扩展,它是execpathor的同义词rootpath(取决于上下文),但它是遗留的,不推荐使用它。

在这里您可以查看有关在 Bazel 中制作变量的官方文档:https ://docs.bazel.build/versions/2.0.0/be/make-variables.html


推荐阅读