如何编写一个genrule来应用补丁

时间:2017-03-08 06:22:13

标签: bazel

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

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

阅读bazel BUILD文档,我发现“出局”是必填字段。但是,我的补丁肯定不会产生任何结果。在Package源代码中只需要2-3行代码更改。我不能保持“出局”为空,也无法在那里添加虚拟文件。有谁可以帮我解决这个问题?

提前致谢, Nishidha

1 个答案:

答案 0 :(得分:3)

如评论中所述,如果你想在一个规则中进行补丁,你需要声明补丁作为输入源,并将结果源作为输出,genrule和Bazel构建不允许修改输入树

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

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

BUILD文件旁边有mypatch.patch个文件(可以为空),local_patched_repository.bzlWORKSPACE。现在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 bug。

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

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