[英]How do you enumerate and copy multiple files to the source folder in Bazel?
How do you enumerate and copy multiple files to the source folder in Bazel?您如何枚举多个文件并将其复制到 Bazel 中的源文件夹?
I'm new to Bazel and I am trying to replace a non-Bazel build step that is effectively cp -R
with an idiomatic Bazel solution.我是 Bazel 的新手,我正在尝试用惯用的 Bazel 解决方案替换实际上是
cp -R
的非 Bazel 构建步骤。 Concrete use cases are:具体用例是:
.proto
files in N Bazel packages, all in one protos/
directory of the repository. .proto
文件,都在存储库的一个protos/
目录中。.gotmpl
template files to a different folder where they can be picked up in a docker volume for a local docker-compose development environment..gotmpl
模板文件复制到不同的文件夹,可以在 docker 卷中为本地 docker-compose 开发环境拾取它们。 There are M template files in one Bazel package in a small folder hierarchy..gotmpl
files to a gitops-type repo for a remote terraform to send to prod..gotmpl
文件复制到 gitops 类型的存储库,以便远程 terraform 发送到产品。 All sources are regular, checked in files in places where Bazel can enumerate them.所有来源都是常规的,在 Bazel 可以枚举它们的地方签入文件。 All target directories are also Bazel packages.
所有目标目录也是 Bazel 包。 I want to write to the source folder, not just to
bazel-bin
, so other non-Bazel tools can see the output files.我想写入源文件夹,而不仅仅是
bazel-bin
,所以其他非 Bazel 工具可以看到 output 文件。
Currently when adding a template file or a proto package, a script must be run outside of bazel to pick up that new file and add it to a generated.bzl file, or perform operations completely outside of Bazel.当前,当添加模板文件或原型 package 时,必须在 bazel 之外运行脚本以获取该新文件并将其添加到 generated.bzl 文件中,或者完全在 Bazel 之外执行操作。 I would like to eliminate this step to move closer to having one true build command.
我想消除这一步,以更接近拥有一个真正的构建命令。
I could accomplish this with symlinks but it still has an error-prone manual step for the.proto files and it would be nice to gain the option to manipulate the files programmatically in Bazel in the build.我可以使用符号链接来完成此操作,但对于 .proto 文件,它仍然有一个容易出错的手动步骤,并且在构建中获得在 Bazel 中以编程方式操作文件的选项会很好。
Some solutions I've looked into and hit dead ends:我研究过的一些解决方案并遇到了死胡同:
glob
seems to be relative to current package and I don't see how it can be exported since it needs to be called from BUILD. glob
似乎与当前的 package 相关,我看不出它是如何导出的,因为它需要从 BUILD 中调用。 A filegroup solves the export issue but doesn't seem to allow enumeration of the underlying files in a way that a bazel run
target can take as input.bazel run
目标可以作为输入的方式枚举基础文件。genquery
and aspects seem to have powerful meta-capabilities but I can't see how to actually accomplish this task with them. genquery
和方面似乎具有强大的元功能,但我看不出如何用它们实际完成这项任务。write_source_files
from aspect-build/bazel-lib
might be great if I could programmatically generate the files
parameter.files
参数,那么“bazel 可以写入源文件夹”模式和aspect-build/bazel-lib
write_source_files
的 write_source_files 可能会很棒。 Here is the template example which is the simpler case.这是模板示例,它是更简单的情况。 This was my latest experiment to bazel-ify
cp -R
.这是我最新的 bazel-ify
cp -R
实验。 I want to express src/templates/update_templates_bzl.py in Bazel.我想在 Bazel 中表达 src/templates/update_templates_bzl.py。
src/templates/BUILD
: src/templates/BUILD
:
# [...]
exports_files(glob(["**/*.gotmpl"]))
# [...]
src/templates/update_templates_bzl.py
: src/templates/update_templates_bzl.py
:
#!/usr/bin/env python
from pathlib import Path
parent = Path(__file__).parent
template_files = [str(f.relative_to(parent)) for f in list(parent.glob('**/*.gotmpl'))]
as_python = repr(template_files).replace(",", ",\n ")
target_bzl = Path(__file__).parent / "templates.bzl"
target_bzl.write_text(f""""Generated template list from {Path(__file__).relative_to(parent)}"
TEMPLATES = {as_python}""")
src/templates/copy_templates.bzl
"""Utility for working with this list of template files"""
load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files")
load("templates.bzl", "TEMPLATES")
def copy_templates(name, prefix):
files = {
"%s/%s" % (prefix, f) : "//src/templates:%s" % f for f in TEMPLATES
}
write_source_files(
name = name,
files = files,
visibility = ["//visibility:public"],
)
other/module
: other/module
:
load("//src/templates:copy_templates.bzl", "copy_templates")
copy_templates(
name = "write_template_files",
prefix = "path/to/gitops/repo/templates",
)
One possible method to do this would be to use google/bazel_rules_install .一种可能的方法是使用google/bazel_rules_install 。
As mentioned in the project README.md you need to add the following to your WORKSPACE file;如项目 README.md 中所述,您需要将以下内容添加到您的 WORKSPACE 文件中;
# file: WORKSPACE
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "com_github_google_rules_install",
urls = ["https://github.com/google/bazel_rules_install/releases/download/0.3/bazel_rules_install-0.3.tar.gz"],
sha256 = "ea2a9f94fed090859589ac851af3a1c6034c5f333804f044f8f094257c33bdb3",
strip_prefix = "bazel_rules_install-0.3",
)
load("@com_github_google_rules_install//:deps.bzl", "install_rules_dependencies")
install_rules_dependencies()
load("@com_github_google_rules_install//:setup.bzl", "install_rules_setup")
install_rules_setup()
Then in your src/templates
directory you can add the following to bundle all your templates into one target.然后在您的
src/templates
目录中,您可以添加以下内容以将所有模板捆绑到一个目标中。
# file: src/templates/BUILD.bazel
load("@com_github_google_rules_install//installer:def.bzl", "installer")
installer(
name = "install_templates",
data = glob(["**/*.gotmpl"]),
)
Then you can use the installer to install into your chosen directory like so.然后您可以使用安装程序安装到您选择的目录中,就像这样。
bazel run //src/templates:install_templates -- path/to/gitops/repo/templates
It's also worth checking out bazelbuild/rules_docker for building your development environments using only Bazel.还值得查看bazelbuild/rules_docker以仅使用 Bazel 构建您的开发环境。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.