我设法构建了我的JNI库(jar,jni共享cc_library,包装的cc_library),但我不知道如何构建使用它的Java应用程序。我的构建很简单:
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)。难道不会发生这种情况吗?
如果我使用单独的步骤构建它们然后尝试运行应用程序(使用bazel-bin中的OCFTestServer包装器),我得到UnsatisfiedLinkError: no libopenocf-jni in java.library.path
。但是从阅读文档中我得到的印象是,这一切都应该自动设置(即所需的jni lib应该放在java.library.path中)。
我做错了什么?有没有人有建立和使用JNI库的例子?
答案 0 :(得分:1)
我创建了一个简单的回购:https://github.com/mhlopko/bazel-jni-example来帮助您入门。
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
的{{1}}。这个例子显然需要更多的润色,因此它适用于Linux以外的平台,因此它适用于启动器脚本。您可能最终需要多次Main.cc
次调用,例如bazel在its windows loader中执行的操作。
答案 1 :(得分:0)
我偶然发现了你的问题,同时试图找出如何链接到我刚刚开始工作的malmo。它链接到一个静态库,所以它可能会或可能不会帮助你。
THIRD_PARTY / BUILD:
java_import(
name = "malmo",
jars = ["MalmoJavaJar.jar"],
deps = [":libMalmo"],
)
cc_library(
name = "libMalmo",
srcs = ["libMalmoJava.so"],
)
然后在我的实际目标中:
"//third_party:malmo",
答案 2 :(得分:0)
实际上,您不需要向cc_library软件包目标中添加bazel local_jdk jni和jni_md标头。但是,您可以将它们复制到您的项目包中。
我已经将PR提交给https://github.com/mhlopko/bazel-jni-example项目,以解决jni相对路径问题。也许这可以帮助您。