如何在 bazel 规则中获取 WORKSPACE 目录
How to get WORKSPACE directory in bazel rule
我为了使用 clang-format
、clang-tidy
等 clang 工具或生成 compilation database like this,我需要知道 .bzl 文件中的 WORKSPACE 目录。我怎样才能得到它?考虑以下示例,其中我只想打印工作区中所有 src 文件的完整路径:
# simple_example.bzl
def _impl(ctx):
workspace_dir = // ---> what comes here? <---
command = "\n".join([echo %s/%s" % (workspace_dir, f.short_path)
for f in ctx.files.srcs])
ctx.actions.write(
output=ctx.outputs.executable,
content=command,
is_executable=True)
echo_full_path = rule(
implementation=_impl,
executable=True,
attrs={
"srcs": attr.label_list(allow_files=True),
}
)
# BUILD
echo_full_path(
name = "echo",
srcs = glob(["src/**/*.cc"])
)
是否有 cleaner/nicer 方法来做到这一点?
您或许可以使用 realpath
来解决这个问题。类似于:
def _impl(ctx):
ctx.actions.run_shell(
inputs = ctx.files.srcs,
outputs = [ctx.outputs.executable],
command = "\n".join(["echo echo $(realpath \"%s\") >> %s" % (f.path,
ctx.outputs.executable.path) for f in ctx.files.srcs]),
execution_requirements = {
"no-sandbox": "1",
"no-cache": "1",
"no-remote": "1",
"local": "1",
},
)
echo_full_path = rule(
implementation=_impl,
executable=True,
attrs={
"srcs": attr.label_list(allow_files=True),
}
)
请注意 execution_requirements
以解决我上面评论中的潜在问题。
如果你像我一样写了一个repository_rule
而不是一个普通的,解析下面的标签可以帮助你:"@//:WORKSPACE"
然后使用ctx.path
提取需要的数据:https://docs.bazel.build/versions/master/skylark/lib/repository_ctx.html#path
我修改了@ahumesky 的规则以隐式使用 BUILD
文件作为源并且只写入工作区目录一次:
workspace.bzl
def _write_workspace_dir_impl(ctx):
src = ctx.files._src[0]
out = ctx.actions.declare_file(ctx.label.name)
ctx.actions.run_shell(
inputs = ctx.files._src,
outputs = [out],
command = """
full_path="$(readlink -f -- "{src_full}")"
# Trim the src.short_path suffix from full_path. Double braces to
# output literal brace for shell.
echo "${{full_path%/{src_short}}}" >> {out_full}
""".format(src_full = src.path, src_short = src.short_path, out_full = out.path),
execution_requirements = {
"no-sandbox": "1",
"no-remote": "1",
"local": "1",
},
)
return [DefaultInfo(files = depset([out]))]
write_workspace_dir = rule(
implementation = _write_workspace_dir_impl,
attrs = {
"_src": attr.label(allow_files = True, default = "BUILD"),
},
doc = "Writes the full path of the current workspace dir to a file.",
)
建造
load(":workspace.bzl", "write_workspace_dir")
write_workspace_dir(
name = "workspace_dir",
)
示例输出
bazel build //build/bazel:workspace_dir
INFO: Analyzed target //build/bazel:workspace_dir
INFO: Build completed successfully, 1 total action
cat bazel-bin/build/bazel/workspace_dir
/p/$MY_PROJECT
我为了使用 clang-format
、clang-tidy
等 clang 工具或生成 compilation database like this,我需要知道 .bzl 文件中的 WORKSPACE 目录。我怎样才能得到它?考虑以下示例,其中我只想打印工作区中所有 src 文件的完整路径:
# simple_example.bzl
def _impl(ctx):
workspace_dir = // ---> what comes here? <---
command = "\n".join([echo %s/%s" % (workspace_dir, f.short_path)
for f in ctx.files.srcs])
ctx.actions.write(
output=ctx.outputs.executable,
content=command,
is_executable=True)
echo_full_path = rule(
implementation=_impl,
executable=True,
attrs={
"srcs": attr.label_list(allow_files=True),
}
)
# BUILD
echo_full_path(
name = "echo",
srcs = glob(["src/**/*.cc"])
)
是否有 cleaner/nicer 方法来做到这一点?
您或许可以使用 realpath
来解决这个问题。类似于:
def _impl(ctx):
ctx.actions.run_shell(
inputs = ctx.files.srcs,
outputs = [ctx.outputs.executable],
command = "\n".join(["echo echo $(realpath \"%s\") >> %s" % (f.path,
ctx.outputs.executable.path) for f in ctx.files.srcs]),
execution_requirements = {
"no-sandbox": "1",
"no-cache": "1",
"no-remote": "1",
"local": "1",
},
)
echo_full_path = rule(
implementation=_impl,
executable=True,
attrs={
"srcs": attr.label_list(allow_files=True),
}
)
请注意 execution_requirements
以解决我上面评论中的潜在问题。
如果你像我一样写了一个repository_rule
而不是一个普通的,解析下面的标签可以帮助你:"@//:WORKSPACE"
然后使用ctx.path
提取需要的数据:https://docs.bazel.build/versions/master/skylark/lib/repository_ctx.html#path
我修改了@ahumesky 的规则以隐式使用 BUILD
文件作为源并且只写入工作区目录一次:
workspace.bzl
def _write_workspace_dir_impl(ctx):
src = ctx.files._src[0]
out = ctx.actions.declare_file(ctx.label.name)
ctx.actions.run_shell(
inputs = ctx.files._src,
outputs = [out],
command = """
full_path="$(readlink -f -- "{src_full}")"
# Trim the src.short_path suffix from full_path. Double braces to
# output literal brace for shell.
echo "${{full_path%/{src_short}}}" >> {out_full}
""".format(src_full = src.path, src_short = src.short_path, out_full = out.path),
execution_requirements = {
"no-sandbox": "1",
"no-remote": "1",
"local": "1",
},
)
return [DefaultInfo(files = depset([out]))]
write_workspace_dir = rule(
implementation = _write_workspace_dir_impl,
attrs = {
"_src": attr.label(allow_files = True, default = "BUILD"),
},
doc = "Writes the full path of the current workspace dir to a file.",
)
建造
load(":workspace.bzl", "write_workspace_dir")
write_workspace_dir(
name = "workspace_dir",
)
示例输出
bazel build //build/bazel:workspace_dir
INFO: Analyzed target //build/bazel:workspace_dir
INFO: Build completed successfully, 1 total action
cat bazel-bin/build/bazel/workspace_dir
/p/$MY_PROJECT