2017-09-16 1 views
2

J'ai réussi à construire ma bibliothèque JNI (le jar, la bibliothèque partagée jni, la cc_library) mais je ne vois pas comment créer une application Java qui l'utilise. Mon BUILD est simple:Bazel: application Java avec dépendance JNI

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

Ici OpenOCF-JNI ressemble à ceci:

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

Et libopenocf est:

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

Tous ces construire avec succès. Cependant, la construction ne provoque pas la construction de dépendances, ce à quoi je m'attendrais (autrement dit, la construction d'OCFTestServer devrait entraîner la construction d'OpenOCF-JNI, ce qui devrait entraîner la construction de libopenocf-jni). Cela ne devrait-il pas arriver? Si je les compile tous en utilisant des étapes séparées, puis que j'essaie d'exécuter l'application (en utilisant l'encapsuleur OCFTestServer dans bazel-bin), j'obtiens UnsatisfiedLinkError: no libopenocf-jni in java.library.path. Mais à la lecture des documents, j'ai l'impression que tout devrait être mis en place automatiquement (c'est-à-dire que la librairie jni nécessaire doit être placée dans le fichier java.library.path).

Qu'est-ce que je fais mal? Quelqu'un at-il un exemple de construction et d'utilisation d'une librairie JNI?

+0

Je pense que votre bibliothèque cc_ est censée séparer ses srcs de ses hdrs. Je ne sais pas si c'est lié. – kd8azz

+0

@ kd8azz: afaik 'hdrs' est pour les en-têtes publics (c'est-à-dire api). sinon, tous les en-têtes sont considérés comme des fichiers sources. – mobileink

+0

Je pense que ceci est répondu ici: https://stackoverflow.com/questions/46160790/bazel-for-jni-jni-h-file-not-found – mhlopko

Répondre

0

Je suis tombé sur votre question, tout en essayant de comprendre comment lier malmo, que je viens de travailler. C'est un lien avec une bibliothèque statique, cela peut ou peut ne pas vous aider.

third_party/BUILD:

java_import(
    name = "malmo", 
    jars = ["MalmoJavaJar.jar"], 
    deps = [":libMalmo"], 
) 

cc_library(
    name = "libMalmo", 
    srcs = ["libMalmoJava.so"], 
) 

Et puis dans ma cible réelle:

"//third_party:malmo", 
1

J'ai créé une prise en pension simple: https://github.com/mhlopko/bazel-jni-example pour vous aider à démarrer.

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; 
} 

Maintenant, en exécutant bazel run :Main, vous devriez voir 42 imprimé, cela vient de Main.cc. L'exemple a clairement besoin de plus de poli pour fonctionner sur des plates-formes autres que Linux, et donc il fonctionne avec le script du lanceur. Vous pourriez avoir besoin de plusieurs appels System.loadLibrary, comme le fait bazel dans its windows loader.

+0

merci. q: pourquoi ': libmain-jni.so' dans' data' plutôt que 'deps'? – mobileink

+0

ou "runtime_deps" d'ailleurs. – mobileink

+0

L'utilisation de données ou de sauvegardes n'est qu'une question de style ici. L'effet est le même puisque les données sont en fait un binaire cc, ce qui est autorisé en tant que dépendance de java_library. –