【问题标题】:How to write a genrule to apply a patch如何编写一个类型来应用补丁
【发布时间】:2017-03-10 20:02:46
【问题描述】:

我正在尝试在 bazel BUILD 中为其中一个包编写一个 genrule。目的是该规则必须在包源上应用一个补丁。我写的如下-

genrule(
    name = "patching_rule",
    srcs = ["Package"],
    outs = ["test_output.txt"],
    cmd = "cd $(location Package); patch -p0 < /tmp/mypatch.patch",
)

阅读 bazel BUILD 文档后,我知道“out”是必填字段。但是,我的补丁肯定不会产生任何结果。它将在包源代码中进行 2-3 行代码更改。我不能保持“出局”为空,也无法在那里添加一个虚拟文件。谁能帮我解决这个问题?

提前致谢, 西达

【问题讨论】:

  • 你能解释一下你为什么要修补你的输入源吗?那棵打补丁的树将如何使用?一般来说,Bazel 不允许修改输入源。
  • 此补丁将应用于外部依赖项。我实际上正在尝试构建张量流。 Tensorflow 确实为我构建而无需任何更改。但是当它构建时,我想在它下载并放入 $HOME/.cache/bazel/_bazel_nishidha/9002cca31b627e38c01a15159b8ff61f/execroot/org_tensorflow/external 的依赖项之一上应用一个补丁。 Tensorflow 有一个针对该依赖项的 BUILD 文件,我正在尝试编写一个 genrule 来对其应用补丁。
  • 哦,好的,您可以为此使用自定义外部存储库,我将在今天晚些时候给出完整的答案。
  • 好的..谢谢达米安。

标签: bazel


【解决方案1】:

正如评论中所说,如果您希望在 genrule 中进行修补,则需要将要修补的源声明为输入,并将结果源声明为输出,genrule 和 Bazel 构建通常不允许修改输入树.

但是,由于此特定情况是用于修补外部存储库 (TensorFlow),因此您可以将 WORKSPACE 文件中您正在使用的任何存储库(可能是 local_repository)替换为自定义实现(我们将其命名为 @987654325 @),所以WORKSPACE 文件部分看起来像:

load("//:local_patched_repository.bzl", "local_patched_repository")
local_patched_repository(
    name = "org_tensorflow",
    path = "tensorflow",
    patch = "//:mypatch.patch",
)

带有BUILD 文件(可以为空),WORKSPACE 文件旁边的mypatch.patchlocal_patched_repository.bzl。现在local_patched_repository.bzl 的内容如下所示:

def _impl(rctxt):
  path = rtcxt.attr.path
  # This path is a bit ugly to get the actual path if it is relative.
  if path[0] != "/":
    # rctxt.path(Label("//:BUILD")) will returns a path to the BUILD file
    # in the current workspace, so getting the dirname get the path
    # relative to the workspace.
    path = rctxt.path(Label("//:BUILD")).dirname + "/" + path
  # Copy the repository
  result = rctxt.execute(["cp", "-fr", path + "/*", rctxt.path()])
  if result.return_code != 0:
    fail("Failed to copy %s (%s)" % (rctxt.attr.path, result.return_code))
  # Now patch the repository
  patch_file = str(rctxt.path(rctxt.attr.patch).realpath)
  result = rctxt.execute(["bash", "-c", "patch -p0 < " + patch_file])
  if result.return_code != 0:
    fail("Failed to patch (%s): %s" % (result.return_code, result.stderr))

local_patched_repository = repository_rule(
    implementation=_impl,
    attrs={
        "path": attr.string(mandatory=True),
        "patch": attr.label(mandatory=True)
    },
    local = True)

当然,这是一个快速的实现,并且有一个问题:local = True 会使这个存储库被重新计算很多,如果修补速度很慢,你可能想要删除它(这意味着我们不会看到变化在 tensorflow 存储库中的文件中)。除非您确实更改了文件,否则它不会正常重建,除非您遇到了 bazel 错误。

如果您确实想替换 http_repository,也可以将 cp 替换为 rctx.download_and_extract(但 tensorflow 仍然需要进行一些修改,以使 ./configure 工作,使其与 http_repository 不兼容)。

编辑:A patch to patch on the fly the eigen http_repository on TensorFlow

【讨论】:

  • 谢谢达米安。我会试试这个。很抱歉我之前没有说清楚。 tensorflow 是我要构建的主要存储库/源。我正在尝试修补它下载的特征。我会试试你的回答。
  • 在这种情况下,对于 eigen,您最好使用下一部分中提到的 download_and_extract。
  • 我已按照建议进行了更改。但是现在,我遇到了错误 -ERROR: /home/nishidha/pkgbuild/tensorflow/tensorflow/third_party/eigen3/BUILD:14:1: no such package '@eigen_archive//': is referenced by '//third_party/eigen3:eigen3'.
  • 不知何故,我认为 local_patched_repository 没有被识别,因为据说 eigen_archive 是“没有这样的包”。如果我使用现有的自定义 repo 规则“temp_workaround_http_archive”,而不是 local_patched_repository,它可以工作。我错过了什么?我也检查了其他地方,但没有发现任何线索。
  • 我终于让它工作了。问题在于 _impl() 函数中“cmd”的形成方式。非常感谢 Damien 的大力帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-07
  • 2013-08-31
  • 1970-01-01
  • 2011-07-08
  • 2017-06-07
  • 1970-01-01
  • 2017-08-18
相关资源
最近更新 更多