使用 Bazel 构建多语言项目
Usage of Bazel to build polyglot projects
我有一个 Kotlin JVM 项目,它在本机运行时中运行一些 JavaScript。目前,不同的语言源定义在不同的仓库中,JS 文件被 webpack 打包成 JAR 指定为 JVM 项目的依赖。这工作正常,但我想合并这两个存储库,因为它们本质上是耦合的。与其维护大量不同的构建工具,我认为这是学习和使用多语言构建系统(如 Bazel)的好机会。
当前结构:
基本上,我要构建两个主要包。 web 包构建正确,我可以通过命令行查看 webpacked 输出。包括网络 BUILD
完整图片文件:
load("@npm_bazel_typescript//:index.bzl", "ts_library")
ts_library(
name = "compileCore",
srcs = ["index.ts"],
tsconfig = "tsconfig.json",
)
filegroup(
name = "internalCore",
srcs = ["compileCore"],
output_group = "es5_sources",
)
load("@npm//webpack-cli:index.bzl", webpack = "webpack_cli")
webpack(
name = "bundle",
outs = ["bundle.prod.js"],
args = [
"--mode production",
"$(execpath internalCore)",
"--config",
"$(execpath webpack.config.js)",
"-o",
"$@",
],
data = [
"internalCore",
"webpack.config.js",
"@npm//:node_modules",
],
visibility = ["//visibility:public"],
)
另一个重要的包是嵌套的 //jvm/src/main/java/com/example/bazel/plugin
包。这基本上是最终的交付物,它应该是一个 JAR,其中包含作为资源的 Web 包的输出。
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
kt_jvm_library(
name = "plugin",
srcs = glob(["*.kt"]),
deps = [
# ... some deps
],
resources = ["//web:bundle"],
visibility = ["//visibility:public"],
)
这看似简单,但在构建过程中出错:
❯ bazel build //jvm/src/...
INFO: Analyzed target //jvm/src/main/java/com/example/bazel/plugin:plugin (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
ERROR: /Users/jzucker/dev/GitHub/plugin-example-bazel/jvm/src/main/java/com/example/bazel/plugin/BUILD:12:15: error executing shell command: '/bin/bash -c external/bazel_tools/tools/zip/zipper/zipper c bazel-out/darwin-fastbuild/bin/jvm/src/main/java/com/example/bazel/plugin/plugin-resources.jar @bazel-out/darwin-fastbuild/bin/jvm/src/ma...' failed (Exit 255) bash failed: error executing command /bin/bash -c ... (remaining 1 argument(s) skipped)
Use --sandbox_debug to see verbose messages from the sandbox
File web/bundle.prod.js does not seem to exist.Target //jvm/src/main/java/com/example/bazel/plugin:plugin failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.402s, Critical Path: 0.05s
INFO: 0 processes.
FAILED: Build did NOT complete successfully
经过一些实验后,这似乎是试图将生成的输出捆绑为 kt_jvm_library
资源的问题。如果资源引用了另一个包中的有形源文件,那么它就可以正常工作。这里的主要问题是这是否是 Bazel 的正确模式,或者我是否试图滥用这项技术。这似乎是一个相对简单的用例,但文档中有一行是我最关心的:
An invariant of all rules is that the files generated by a rule always belong to the same package as the rule itself; it is not possible to generate files into another package. It is not uncommon for a rule's inputs to come from another package, though.
来自https://docs.bazel.build/versions/master/build-ref.html
如有任何见解,我们将不胜感激。
这实际上是 Bazel Kotlin 规则集中的一个错误:
github.com/bazelbuild/rules_kotlin/issues/281
在修复之前,您可以将资源打包在 java_library
中并将其包含为 resource_jars
。
java_library(
name = "resources",
resources = ["//web:bundle"],
resource_strip_prefix = "web",
)
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
kt_jvm_library(
name = "plugin",
srcs = glob(["*.kt"]),
deps = [
# ... some deps
],
resource_jars = ["resources"],
visibility = ["//visibility:public"],
)
我有一个 Kotlin JVM 项目,它在本机运行时中运行一些 JavaScript。目前,不同的语言源定义在不同的仓库中,JS 文件被 webpack 打包成 JAR 指定为 JVM 项目的依赖。这工作正常,但我想合并这两个存储库,因为它们本质上是耦合的。与其维护大量不同的构建工具,我认为这是学习和使用多语言构建系统(如 Bazel)的好机会。
当前结构:
基本上,我要构建两个主要包。 web 包构建正确,我可以通过命令行查看 webpacked 输出。包括网络 BUILD
完整图片文件:
load("@npm_bazel_typescript//:index.bzl", "ts_library")
ts_library(
name = "compileCore",
srcs = ["index.ts"],
tsconfig = "tsconfig.json",
)
filegroup(
name = "internalCore",
srcs = ["compileCore"],
output_group = "es5_sources",
)
load("@npm//webpack-cli:index.bzl", webpack = "webpack_cli")
webpack(
name = "bundle",
outs = ["bundle.prod.js"],
args = [
"--mode production",
"$(execpath internalCore)",
"--config",
"$(execpath webpack.config.js)",
"-o",
"$@",
],
data = [
"internalCore",
"webpack.config.js",
"@npm//:node_modules",
],
visibility = ["//visibility:public"],
)
另一个重要的包是嵌套的 //jvm/src/main/java/com/example/bazel/plugin
包。这基本上是最终的交付物,它应该是一个 JAR,其中包含作为资源的 Web 包的输出。
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
kt_jvm_library(
name = "plugin",
srcs = glob(["*.kt"]),
deps = [
# ... some deps
],
resources = ["//web:bundle"],
visibility = ["//visibility:public"],
)
这看似简单,但在构建过程中出错:
❯ bazel build //jvm/src/...
INFO: Analyzed target //jvm/src/main/java/com/example/bazel/plugin:plugin (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
ERROR: /Users/jzucker/dev/GitHub/plugin-example-bazel/jvm/src/main/java/com/example/bazel/plugin/BUILD:12:15: error executing shell command: '/bin/bash -c external/bazel_tools/tools/zip/zipper/zipper c bazel-out/darwin-fastbuild/bin/jvm/src/main/java/com/example/bazel/plugin/plugin-resources.jar @bazel-out/darwin-fastbuild/bin/jvm/src/ma...' failed (Exit 255) bash failed: error executing command /bin/bash -c ... (remaining 1 argument(s) skipped)
Use --sandbox_debug to see verbose messages from the sandbox
File web/bundle.prod.js does not seem to exist.Target //jvm/src/main/java/com/example/bazel/plugin:plugin failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.402s, Critical Path: 0.05s
INFO: 0 processes.
FAILED: Build did NOT complete successfully
经过一些实验后,这似乎是试图将生成的输出捆绑为 kt_jvm_library
资源的问题。如果资源引用了另一个包中的有形源文件,那么它就可以正常工作。这里的主要问题是这是否是 Bazel 的正确模式,或者我是否试图滥用这项技术。这似乎是一个相对简单的用例,但文档中有一行是我最关心的:
An invariant of all rules is that the files generated by a rule always belong to the same package as the rule itself; it is not possible to generate files into another package. It is not uncommon for a rule's inputs to come from another package, though.
来自https://docs.bazel.build/versions/master/build-ref.html
如有任何见解,我们将不胜感激。
这实际上是 Bazel Kotlin 规则集中的一个错误: github.com/bazelbuild/rules_kotlin/issues/281
在修复之前,您可以将资源打包在 java_library
中并将其包含为 resource_jars
。
java_library(
name = "resources",
resources = ["//web:bundle"],
resource_strip_prefix = "web",
)
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
kt_jvm_library(
name = "plugin",
srcs = glob(["*.kt"]),
deps = [
# ... some deps
],
resource_jars = ["resources"],
visibility = ["//visibility:public"],
)