Search code examples
cmakejava-native-interfaceimagej

Encapsulating a JNI library inside a jar file


I am trying to develop a plugin for Fiji/ImageJ that relies on a native library (JNI). The JNI library itself depends on libtiff and fftw. On OSX and Linux, I use the class NativeUtils and everything works fine.

On windows, I included binary versions of libtiff and fftw in the CMake package and managed to link the JNI library against those (either statically of dynamically). However, the resulting JNI module does not include libtiff or fftw and I obtain an error when I try to load the JNI library with NativeUtils.loadLibraryFromJar. This is also the case when I include the dependent .dll in the .jar since they are not extracted by NativeUtils.

Here are the relevant lines in CMakeLists.txt:

add_library(fftw STATIC IMPORTED GLOBAL)
set_target_properties(fftw PROPERTIES IMPORTED_LOCATION "${libdir}/libfftw3f-3.lib"
                                      INTERFACE_INCLUDE_DIRECTORIES  "${incdir}")

SWIG_ADD_LIBRARY(javainterf
                 TYPE MODULE
                 LANGUAGE java
                 SOURCES javainterf.i javainterf.c src1.c)
SWIG_LINK_LIBRARIES(javainterf libcode1 fftw)

add_jar(Foo
        SOURCES ${CMAKE_CURRENT_BINARY_DIR}/java/foo1.java
        INCLUDE_JARS java/resources/ij-1.51p.jar
        VERSION ${JAR_VERSION})
add_dependencies(Foo javainterf)
add_custom_command(TARGET Foo POST_BUILD
    COMMAND "${Java_JAR_EXECUTABLE}" -uf Foo-${JAR_VERSION}.jar
    -C ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} ${JNI_LIB_NAME})

How would you make sure that all the dependencies are properly included in the jar and loaded?


Solution

  • You can't load library from inside JAR without extracting it in a first place.

    Take a look here at full sample where native code is embedded inside JAR and extracted when needed.

    https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031

    Update

    Well, in that case, when you need to pack more libs and you want to properly resolve locations, you need to play with runtime env a little bit.

    Take a look here:

    https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo035

    git clone https://github.com/mkowsiak/jnicookbook
    cd jnicookbook/recipes/recipeNo035
    make
    make test
    

    Have fun with JNI!