Как я могу включить и использовать внешнюю библиотеку C ++ в библиотеке JNI Gradle? - PullRequest
0 голосов
/ 12 марта 2020

Я пытаюсь написать Java привязок для библиотеки C ++ и пытаюсь использовать для нее gradle.

Если у меня есть заголовок try.h и общая библиотека libtry.so, я хочу использовать его в моем проекте gradle. Я пытаюсь сделать это следующим образом:

Вот файл build.gradle:

import org.gradle.internal.jvm.Jvm

/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java Library project to get you started.
 * For more details take a look at the Java Libraries chapter in the Gradle
 * User Manual available at https://docs.gradle.org/6.2.2/userguide/java_library_plugin.html
 */

plugins {
    // Apply the java-library plugin to add support for Java Library
    id 'java-library'
    id 'cpp'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
    // This dependency is exported to consumers, that is to say found on their compile classpath.
    api 'org.apache.commons:commons-math3:3.6.1'

    // This dependency is used internally, and not exposed to consumers on their own compile classpath.
    implementation 'com.google.guava:guava:28.1-jre'

    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'
}
test {
    systemProperty "java.library.path", file("${buildDir}/libs/hello/shared").absolutePath
}

model {
    platforms {
        x64 {
            architecture "x64"
        }
    }

    components {
        hello(NativeLibrarySpec) {
            binaries.all {
                if (targetPlatform.operatingSystem.macOsX) {
                    cppCompiler.args '-I', "${Jvm.current().javaHome}/include"
                    cppCompiler.args '-I', "${Jvm.current().javaHome}/include/darwin"
                    cppCompiler.args '-I', "/home/karthik/gradle_try/HelloWorld/libs"
                    cppCompiler.args '-L', "/home/karthik/gradle_try/HelloWorld/libs"
                    cppCompiler.args '-l', "try"
                    cppCompiler.args '-mmacosx-version-min=10.4'
                    linker.args '-mmacosx-version-min=10.4'
                } else if (targetPlatform.operatingSystem.linux) {
                    cppCompiler.args '-I', "${Jvm.current().javaHome}/include"
                    cppCompiler.args '-I', "${Jvm.current().javaHome}/include/linux"
                    cppCompiler.args '-I', "/home/karthik/gradle_try/HelloWorld/libs"
                    cppCompiler.args '-L', "/home/karthik/gradle_try/HelloWorld/libs"
                    cppCompiler.args '-l', "try"
                    cppCompiler.args '-D_FILE_OFFSET_BITS=64'
                } else if (targetPlatform.operatingSystem.windows) {
                    cppCompiler.args "-I${Jvm.current().javaHome}/include"
                    cppCompiler.args "-I${Jvm.current().javaHome}/include/win32"
                    cppCompiler.args '-I', "/home/karthik/gradle_try/HelloWorld/libs"
                    cppCompiler.args '-L', "/home/karthik/gradle_try/HelloWorld/libs"
                    cppCompiler.args '-l', "try"
                    linker.args "Shlwapi.lib", "Advapi32.lib"
                } else if (targetPlatform.operatingSystem.freeBSD) {
                    cppCompiler.args '-I', "${Jvm.current().javaHome}/include"
                    cppCompiler.args '-I', "${Jvm.current().javaHome}/include/freebsd"
                    cppCompiler.args '-I', "/home/karthik/gradle_try/HelloWorld/libs"
                    cppCompiler.args '-L', "/home/karthik/gradle_try/HelloWorld/libs"
                    cppCompiler.args '-l', "try"
                }
            }
        }
    }
}

test.dependsOn 'helloSharedLibrary'

Другие соответствующие файлы находятся ниже:

hello.h

#include <jni.h>
/* Header for class HelloWorld_Library */

#ifndef _Included_HelloWorld_Library
#define _Included_HelloWorld_Library
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld_Library
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_Library_print
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

hello.cpp

#include "hello.h"
#include <try.h>
#include<iostream>

void Java_HelloWorld_Library_print(JNIEnv *env, jobject object)
{
    ABC abc;
    abc.sayFive();
    std::cout<<"Hello World!";
}

Library.java

package HelloWorld;

public class Library {
    public boolean someLibraryMethod() {
        return true;
    }
    public native void print();
    static {
        System.loadLibrary("hello");
    }
}

LibraryTest.java

package HelloWorld;

import org.junit.Test;
import static org.junit.Assert.*;

public class LibraryTest {
    @Test public void testSomeLibraryMethod() {
        Library classUnderTest = new Library();
        classUnderTest.print();
        assertTrue("someLibraryMethod should return 'true'", classUnderTest.someLibraryMethod());
    }
}

При строительстве я получаю эту ошибку:

> Task :test FAILED
/home/karthik/JDK/jdk-13.0.2/bin/java: symbol lookup error: /home/karthik/gradle_try/HelloWorld/build/libs/hello/shared/libhello.so: undefined symbol: _ZN3ABC7sayFiveEv

FAILURE: Build failed with an exception.

Что я делаю не так? Я указал каталог include и каталог ссылок и библиотеку, которые будут связаны в аргументах компилятора. Есть ли другой способ сделать это?

Кроме того, как я могу получить текущий каталог проекта или файл build.gradle? Указывать каталог включения для внешней библиотеки как абсолютный путь совсем не удобно.

...