如何编写规则以应用补丁
How to write a genrule to apply a patch
我正尝试在 bazel BUILD 中为其中一个包编写一个 genrule。目的是规则必须在包源上应用一个补丁。我写的如下 -
genrule(
name = "patching_rule",
srcs = ["Package"],
outs = ["test_output.txt"],
cmd = "cd $(location Package); patch -p0 < /tmp/mypatch.patch",
)
看了bazel BUILD文档,才知道"outs"是必填字段。但是,我的补丁肯定不会生成任何东西。它只是 2-3 行代码更改,它将在包源代码中进行。我不能让 "outs" 为空,也不能在那里添加虚拟文件。谁能帮我解决这个问题?
提前致谢,
西达
✿如评论中所述,如果您希望在 genrule 中打补丁,则需要将要打补丁的源声明为输入,并将生成的源声明为输出,genrule 和 Bazel build 不允许修改输入树一般。
但是,由于此特定案例用于修补外部存储库 (TensorFlow),您可以使用自定义实现替换 WORKSPACE
文件中正在使用的任何存储库(可能是 local_repository
) (我们将其命名为 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.bzl
紧挨着WORKSPACE
文件。现在 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
,你也可以用 rctx.download_and_extract 替换 cp
(但 tensorflow 仍然需要一些修改,./configure 工作,使其与 http_repository
).
编辑:A patch to patch on the fly the eigen http_repository on TensorFlow
我正尝试在 bazel BUILD 中为其中一个包编写一个 genrule。目的是规则必须在包源上应用一个补丁。我写的如下 -
genrule(
name = "patching_rule",
srcs = ["Package"],
outs = ["test_output.txt"],
cmd = "cd $(location Package); patch -p0 < /tmp/mypatch.patch",
)
看了bazel BUILD文档,才知道"outs"是必填字段。但是,我的补丁肯定不会生成任何东西。它只是 2-3 行代码更改,它将在包源代码中进行。我不能让 "outs" 为空,也不能在那里添加虚拟文件。谁能帮我解决这个问题?
提前致谢, 西达
✿如评论中所述,如果您希望在 genrule 中打补丁,则需要将要打补丁的源声明为输入,并将生成的源声明为输出,genrule 和 Bazel build 不允许修改输入树一般。
但是,由于此特定案例用于修补外部存储库 (TensorFlow),您可以使用自定义实现替换 WORKSPACE
文件中正在使用的任何存储库(可能是 local_repository
) (我们将其命名为 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.bzl
紧挨着WORKSPACE
文件。现在 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
,你也可以用 rctx.download_and_extract 替换 cp
(但 tensorflow 仍然需要一些修改,./configure 工作,使其与 http_repository
).
编辑:A patch to patch on the fly the eigen http_repository on TensorFlow