Bazel:具有JNI依赖关系的Java应用程序 [英] Bazel: Java app with JNI dependency

查看:201
本文介绍了Bazel:具有JNI依赖关系的Java应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设法构建了JNI库(jar,jni共享cc_library,包装的cc_library),但是我看不到如何构建使用它的Java应用程序.我的构建很简单:

I've managed to build my JNI library (the jar, the jni shared cc_library, the wrapped cc_library) but I don't see how to build a Java app that uses it. My BUILD is simple:

java_binary(
    name = "OCFTestServer",
    srcs = glob(["src/main/java/**/*.java"]),
    deps = ["//:OpenOCF-JNI"])

此处OpenOCF-JNI看起来像这样:

java_library(
    name = "OpenOCF-JNI",
    srcs = glob(["src/main/**/*.java"]),
    deps = ["libopenocf"],
    visibility = ["//visibility:public"])

libopenocf是:

cc_library(
    name = "libopenocf",
    srcs = glob(["src/c/*.c"]) + glob(["src/c/*.h"])
    + ["@local_jdk//:jni_header",
       "@local_jdk//:jni_md_header-darwin"],
    ... etc ...

所有这些都成功构建.但是,构建不会导致构建依赖关系,这是我期望的(即构建OCFTestServer应该导致构建OpenOCF-JNI,这应该导致构建libopenocf-jni).那不应该发生吗?

These all build successfully. However, building does not cause dependencies to be built, which is what I would expect (i.e. building OCFTestServer should cause OpenOCF-JNI to be built, which should cause libopenocf-jni to be built). Shouldn't that happen?

如果我使用单独的步骤来构建它们,然后尝试运行应用程序(使用bazel-bin中的OCFTestServer包装器),则会得到UnsatisfiedLinkError: no libopenocf-jni in java.library.path.但是从阅读文档后,我得到的印象是,所有这些都应该自动设置(即,所需的jni lib应该放在java.library.path中).

If I build them all using separate steps and then try to run the application (using the OCFTestServer wrapper in bazel-bin), I get UnsatisfiedLinkError: no libopenocf-jni in java.library.path. But from reading the docs I get the impression that this should all be set up automatically (i.e. the needed jni lib should be put in the java.library.path).

我做错了什么?有人有构建和使用JNI库的示例吗?

What am I doing wrong? Does anybody have an example of building and using a JNI lib?

推荐答案

我创建了一个简单的存储库: https://github.com/mhlopko/bazel-jni-example 帮助您入门.

I created a simple repo: https://github.com/mhlopko/bazel-jni-example to help you get started.

BUILD:

cc_library(
    name = "main-jni-lib",
    srcs = [
        "@local_jdk//:jni_header",
        "@local_jdk//:jni_md_header-linux",
        "Main.cc"
        ],
    hdrs = [ "Main.h" ],
    includes = [ "external/local_jdk/include", "external/local_jdk/include/linux" ],
)

cc_binary(
    name = "libmain-jni.so",
    deps = [ ":main-jni-lib" ],
    linkshared = 1,
)

java_binary(
    name = "Main",
    srcs = [ "Main.java" ],
    main_class = "Main",
    data = [ ":libmain-jni.so" ],
    jvm_flags = [ "-Djava.library.path=." ],
)

Main.java:

public class Main {
  static {
    System.loadLibrary("main-jni");
  }

  private native int foo();

  public static void main(String[] args) {
    System.out.println(new Main().foo());
  }
}

Main.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Main */

#ifndef _Included_Main
#define _Included_Main
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Main
 * Method:    foo
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_Main_foo(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Main.cc:

#include <jni.h>
#include <stdio.h>
#include "Main.h"

JNIEXPORT jint JNICALL Java_Main_foo(JNIEnv *, jobject) {
   return 42;
}

现在,通过运行bazel run :Main,您应该看到打印出的42,它是来自Main.cc的.该示例显然需要更多改进,因此它可以在非Linux平台上工作,因此可以与启动器脚本一起工作.您可能最终需要多次System.loadLibrary调用,就像

Now by running bazel run :Main you should see 42 printed out, that is coming from Main.cc. The example clearly needs more polish so it works on other-than-linux platforms, and so it works with the launcher script. You might end up needing multiple System.loadLibrary calls, like bazel does in its windows loader.

这篇关于Bazel:具有JNI依赖关系的Java应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆