Hello,
I would like to get some expert advice / feedback on the approach I am taking to generate the JNI headers.
I’m writing a Java library using the java-library plugin. The library includes native methods and objects.
I need to handle the generation of the JNI headers as part of the library build process. The headers, together with some ‘externally built’ C++ stubs and cmake files, would then be placed in a directory and assembled in a tar file (for later build on the target machine).
Since java 9, javah is no longer available and the generation of the JNI headers is obrained via javac -h together with the .class file generation.
The approach I took is to create a custom task generateJniHeaders of type JavaCompile, customized (using -h and -d options) to generate the .class files to a temporaty folder and the header files to a jni folder, and then as a doLast action remove the temporary folder.
The jni folder is set as the destinationDir so that other tasks can depend on the task output (containing the JNI headers) properly.
This works but seems to me a little ugly as I am compiling the java files two times just to throw away the second compilation.
Here’s the snippet:
task generateJniHeaders(type: JavaCompile) { classpath = sourceSets.main.compileClasspath destinationDir file("${buildDir}/generated/jni") source = sourceSets.main.java options.compilerArgs += [ '-h', file("${buildDir}/generated/jni"), '-d', file("${buildDir}/generated/jni-tmp") ] // options.verbose = true doLast { delete file("${buildDir}/generated/jni-tmp") } }
I have also tested another approach, customizing the standard compileJava task adding the -h flag and generating the headers to a separate directory. In this case I don’t know how to make other tasks that need to assemble the headers and the C++ stubs to depend on the JNI headers output created by the compileJava task.
I know I could create a custom compileJavaXX task extending JavaCompile defining an additional output that other tasks could depend on, but this would then mean having to customize the standard java build process for the main sourceSet.
I am far from being a gradle expert so I’m thinking there is probably a much better way which is more in line with the best practices…
I am running gradle 5.6.1 on Windows 10, Eclipse 4.13.0, Java JDK 11
Any suggestion would be greately appreciated.
GP