2

我的项目中有一个棘手的模块,除了 Maven,它(还)不能由任何东西构建。好消息是这个模块在我的项目中没有任何 Java 依赖项,它只生成一个.war文件,我需要将它移动到输出 zip 分发中的正确位置。

我想将构建迁移到 bazel,但我想在迁移的后期处理棘手的模块。

如何在我的 bazel 构建中运行 mvn 作为工具,让它生成 .war 文件?

  • Maven 期望从包含pom.xml
  • Maven 将输出写入输入文件树的子目录
  • 当 settings.xml 包含绝对路径时,Maven 是最快乐的(到 .war 的本地 maven 存储库,存储在 git 中)
  • Maven 使用 $HOME/.m2 进行缓存

我查看了 rules_foreign_cc,它围绕 cmake 创建了一个包装脚本。这是要走的路吗?https://github.com/bazelbuild/rules_foreign_cc/blob/8372f383cf7277a88762efe25d8cfee10ad27929/tools/build_defs/framework.bzl#L156

4

1 回答 1

3

我在这个拉取请求mvn_package中有一个规则原型。你提出的观点很关键;在 Bazel 更严格的动作执行环境中驯服 Maven 的约定和期望需要一点时间。

Maven 期望从包含 pom.xml 的目录中执行

您可以使用该-f标志来指定pom.xml.

例如mvn package -f %s -DskipTests -DbazelOutputDir=%s -Pbazel" % (ctx.file.pom_xml.dirname,output_jar.dirname)

Maven 将输出写入输入文件树的子目录

我在pom.xmlto 中为自定义 Maven 定义创建了一个自定义配置文件,并通过了上面的命令行定义:

    <profiles>
        <profile>
            <id>bazel</id>
            <build>
                <directory>${bazelOutputDir}</directory>
            </build>
        </profile>
    </profiles>

当 settings.xml 包含绝对路径时,Maven 是最快乐的(到 .war 的本地 maven 存储库,存储在 git 中)

这很不幸,您必须找到解决方法或禁用沙盒:(

Maven 使用 $HOME/.m2 进行缓存

只要在 Starlark 规则中正确声明了 Bazel 操作输入和输出,您就不需要与 Maven 的 .m2 缓存目录进行交互,因为 Bazel 有自己的操作缓存。

为了完整起见,这里是一个 Starlark 规则的概念证明来打包一个 .jar,所以你可能需要为一个 .war 调整它:

def _mvn_package_impl(ctx):
    inputs = []
    inputs.extend(ctx.files.srcs)
    inputs.append(ctx.file.pom_xml)

    output_jar = ctx.actions.declare_file("target/%s-%s.jar" % (ctx.attr.artifact_id, ctx.attr.version))
    target_dir = ctx.actions.declare_directory("target")
    outputs = [output_jar, target_dir]

    # -Djar.finalName=custom-jar-name
    ctx.actions.run_shell(
        inputs = inputs,
        outputs = outputs,
        mnemonic = "MvnPackage",
        progress_message = "Running 'mvn package' for %s" % output_jar.short_path,
        command = "mvn package -f %s -DskipTests -DbazelOutputDir=%s -Pbazel" % (ctx.file.pom_xml.dirname,output_jar.dirname),
    )

    return [
        DefaultInfo(
            files = depset(outputs),
        ),
        JavaInfo(
            output_jar = output_jar,
            compile_jar = output_jar,
        ),
    ]

mvn_package = rule(
    implementation = _mvn_package_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = True, allow_empty = False),
        "pom_xml": attr.label(allow_single_file = True, mandatory = True),
        "artifact_id": attr.string(mandatory = True),
        "group_id": attr.string(mandatory = True),
        "version": attr.string(mandatory = True),
    },
) 

并在 BUILD 文件中使用上述规则:

load("@rules_jvm_external//:mvn.bzl", "mvn_package")

mvn_package(
    name = "hello_maven",
    srcs = [
        "//src/main/java/hello:srcs",
    ],
    pom_xml = "//:pom.xml",
    group_id = "org.springframework",
    artifact_id = "gs-spring-boot",
    version = "0.1.0",
)

java_binary(
    name = "hello_maven_app",
    runtime_deps = [":hello_maven"],
    main_class = "hello.Application",
)
于 2020-04-30T09:35:51.233 回答