gpt4 book ai didi

使用 Bazel 增强 Datanucleus

转载 作者:行者123 更新时间:2023-12-04 03:30:05 30 4
gpt4 key购买 nike

我正在尝试将 Maven 项目迁移到 Bazel,但在 Datanucleus 增强方面遇到了麻烦。

jar -file 已构建,Datanucleus 会查看其中的内部并执行一些字节码操作以增强可持久化的类。在 Bazel 中执行此操作的方法是定义一个采用 *.jar 的规则。 java_library 的输出规则并创建库的新增强版本。

我的问题是,对于我的规则,我需要 datanucleus-core来自外部库的包。当我尝试从 genrule 访问它时来自 $(location //third_party:datanucleus_core)它指向一个没有类的 jar :

(genrule) cmd = "echo $(location //third_party:datanucleus_core)"
bazel-out/local-fastbuild/bin/third_party/liborg_datanucleus_datanucleus_core.jar

(genrule) cmd = "jar tf $(location //third_party:datanucleus_core)"
META-INF/
META-INF/MANIFEST.MF
jar -文件由 Bazel 在 genrule 中解析来自 $(location //third_party:datanucleus_core)仅包含 META-INF/MANIFEST.MF具有以下内容:
Manifest-Version: 1.0
Created-By: blaze

我尝试使用 java_binary添加正确的规则 datanucleus_core.jar进入类路径,但 Datanucleus 就地增强了我的库并且无法将其更改写入磁盘(重写规则的输入文件)。还有 java_binary规则不应该用于构建。

所以问题是什么是最好的增强方式 jar运行 Datanucleus 实用程序的 Bazel 中的库,它作为 Maven 存储库中的第三方依赖项提供?

Bazel 构建标签: 0.3.2-homebrew , 操作系统: OS X El Capitan (10.11.6) , java: 1.8.0_92
更新

Datanucleus 依赖声明:
# WORKSPACE
maven_jar(
name = "org_datanucleus_datanucleus_core",
artifact = "org.datanucleus:datanucleus-core:5.0.3",
)

# third_party/BUILD
java_library(
name = "org_datanucleus_datanucleus_core",
visibility = ["//visibility:public"],
exports = ["@org_datanucleus_datanucleus_core//jar"],
)

(在我的问题中,我将 org_datanucleus_datanucleus_core 缩短为 datanucleus_core )

最佳答案

正如尼尔斯托克顿所提到的,你不能在 jar 里增强类。因此,基本策略将是:

  • 创建 jar 。
  • 解压类文件。
  • 运行增强功能。
  • 把它备份起来。

  • 第 2 步和第 3 步必须合并为第 4 步,因为 Bazel 坚持要求您将所有输入和输出声明为构建规则(并且您无法知道 .java 文件将生成哪些 .class 文件,因此 Bazel 总是将它们打包)。

    创建一个 datanucleus.bzl文件来声明您的增强规则。它应该类似于:
    # Run datastore enhancements on the java_library named "jarname".
    def enhance(jarname):
    # src is the name of the jar file your java_library rule generates.
    src = "lib" + jarname + ".jar"
    native.genrule(
    name = jarname + "-enhancement",
    srcs = [
    src,
    "//third_party:datanucleus_core"
    ],
    outs = [jarname + "-enhanced.jar"],
    cmd = """
    # Un-jar the .class files.
    jar tf $(location {0})
    # Run the enhance.
    classes=""
    for $$class in $$(find . -name *.class); do
    java -cp {0}:$(location //third_party:datanucleus_core) $$class
    classes="$$classes $$class"
    done
    # jar them back up.
    jar cf $@ $$classes""".format(src),
    )

    (我对数据存储不太熟悉,所以 cmd 可能需要一些修改,但应该是一般的想法。)

    然后,在您的 BUILD 文件中,您将执行以下操作:
    java_library(
    name = "my-lib",
    srcs = glob(["*.java"]),
    deps = ["..."],
    )

    # import the rule you wrote.
    load('//:datanucleus.bzl', 'enhance')
    enhance("my-lib")

    现在你可以这样做:
    bazel build //:my-lib-enhanced.jar

    并使用 my-lib-enhanced.jar作为其他 java_ 的依赖项规则。

    有关 .bzl 文件的更多信息: https://bazel.build/versions/master/docs/skylark/concepts.html .

    编辑以根据 jar 添加更多信息:

    有几个选项可以获取包含 datanucleus 内容的 jar。首先,你不需要间接层:你可以说:
          srcs = [
    src,
    "@datanucleus_core//jar"
    ],

    这将为您提供实际的 jar 。

    如果出于某种原因,您需要将 jar 放在第三方中,您可以修改 third_party/BUILD 以创建一个部署 jar,它是一个 java 二进制文件,它捆绑了所有用于部署的依赖项(因为您实际上不会使用它作为二进制文件,你可以使用任何你想要的主类名):
    java_binary(
    name = "datanucleus-core",
    main_class = "whatever",
    runtime_deps = ["@org_datanucleus_datanucleus_core//jar"],
    )

    genrule(
    name = "your-lib",
    srcs = [":datanucleus-core_deploy.jar", ...],
    )
    :datanucleus-core_deploy.jar被称为隐式目标:它仅在请求时构建,但它可以从您的 java_binary 生成宣言。

    关于使用 Bazel 增强 Datanucleus,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40337396/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com