简体   繁体   English

您如何枚举多个文件并将其复制到 Bazel 中的源文件夹?

[英]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:具体用例是:

  • copying.proto files to aa sub-project where they will be picked up by a non-Bazel build system.将.proto 文件复制到一个子项目,在那里它们将被非 Bazel 构建系统拾取。 There are N .proto files in N Bazel packages, all in one protos/ directory of the repository. N 个 Bazel 包中有 N .proto文件,都在存储库的一个protos/目录中。
  • copying numerous .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.在一个小文件夹层次结构中,一个 Bazel package 中有 M 个模板文件。 Example code below.下面的示例代码。
  • Copy those same .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目标可以作为输入的方式枚举基础文件。
  • Rules like cc_library that happily input globs as srcs are built into the Bazel source code, not written in Starlark像 cc_library 这样愉快地将 glob 作为 src 输入的规则内置在 Bazel 源代码中,而不是用 Starlark 编写的
  • genquery and aspects seem to have powerful meta-capabilities but I can't see how to actually accomplish this task with them. genquery和方面似乎具有强大的元功能,但我看不出如何用它们实际完成这项任务。
  • The "bazel can write to the source folder" pattern and 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM