user1723095
user1723095

Reputation: 1219

Best way to define javah task in gradle

I'm fairly new to gradle and groovy. Here is my task that generates JNI headers:

apply plugin: 'java'
apply plugin: 'application'

mainClassName = "com.my.example.HelloG"

task GenerateJniHeaders(dependsOn: 'classes') << {
    def classpath = "build/classes/main"
    def nativeIncludes = "src/native/include"
    "javah -d ${nativeIncludes} -classpath ${classpath} ${mainClassName}".execute()
}
classes.finalizedBy GenerateJniHeaders
build.dependsOn GenerateJniHeaders

It works ok but I feel it's a bit ugly. How can I improve it? I appreciate any suggestions, especially those which help me remove variables hardcoded by me. I would also like to make this task more generic - now it only generates JNI header for main class but I would want to run it for all java files. Moreover when this task fails (e.g. classpath is wrong) it doesn't print any error message and build succeed, which is misleading.

Upvotes: 12

Views: 3145

Answers (1)

Amnon Shochot
Amnon Shochot

Reputation: 9386

  1. Gradle has a task type of type Exec with a command line property so it would be more appropriate to use it:

    task generateJniHeaders(type:Exec) {
        def classpath = sourceSets.main.output.classesDir
        def nativeIncludes = "src/native/include"                     
        commandLine "javah", "-d", nativeIncludes, "-classpath", classpath, "$mainClassName"
    
        dependsOn classes
    }
    

    Note that this way everything in this task is a configuration rather than an action (if you're unfamiliar with Gradle's build lifecycle then a recommended reading would be this section in the user guide.

  2. build.dependsOn GenerateJniHeaders should be replaced by jar.dependsOn GenerateJniHeaders

  3. classes.finalizedBy is not needed at all. Note that finalizedBy is usually used for cleanups as it execute even if the task fails.

Upvotes: 15

Related Questions